diff --git a/client/src/pages/A3JobEvaluationForm.jsx b/client/src/pages/A3JobEvaluationForm.jsx
index 72f3c26d0..582ac6db0 100644
--- a/client/src/pages/A3JobEvaluationForm.jsx
+++ b/client/src/pages/A3JobEvaluationForm.jsx
@@ -1,79 +1,103 @@
-import React, { useState, useRef, useEffect } from 'react';
-import { Form, Button, Container, Row, Col, Table, Modal, Tab, Nav } from 'react-bootstrap';
-import SignatureCanvas from 'react-signature-canvas';
-import '../styles/A3JobEvaluationForm.css';
+import React, { useState, useRef, useEffect } from "react";
+import {
+ Form,
+ Button,
+ Container,
+ Row,
+ Col,
+ Table,
+ Modal,
+ Tab,
+ Nav,
+} from "react-bootstrap";
+import SignatureCanvas from "react-signature-canvas";
+import "../styles/A3JobEvaluationForm.css";
// Fonts used for styled signature typing
-const fonts = ['Pacifico', 'Indie Flower', 'Dancing Script', 'Great Vibes', 'Satisfy'];
+const fonts = [
+ "Pacifico",
+ "Indie Flower",
+ "Dancing Script",
+ "Great Vibes",
+ "Satisfy",
+];
// Evaluation criteria items
const evaluationItems = [
- 'Task Execution and Quality',
- 'Initiative and Proactiveness',
- 'Communication and Collaboration',
- 'Time Management and Dependability',
- 'Problem Solving and Critical Thinking',
- 'Creativity and Innovation',
- 'Technical and Industry Specific Skills',
- 'Work Ethic and Cultural Fit',
- 'Feedback Reception and Implementation'
+ "Task Execution and Quality",
+ "Initiative and Proactiveness",
+ "Communication and Collaboration",
+ "Time Management and Dependability",
+ "Problem Solving and Critical Thinking",
+ "Creativity and Innovation",
+ "Technical and Industry Specific Skills",
+ "Work Ethic and Cultural Fit",
+ "Feedback Reception and Implementation",
];
-
const A3JobEvaluationForm = () => {
// Form state management
const [formData, setFormData] = useState({
- advisorSignature: '',
+ advisorSignature: "",
advisorAgreement: false,
- coordinatorSignature: '',
+ coordinatorSignature: "",
coordinatorAgreement: false,
});
- // Ratings and comments
+ // Ratings and comments
const [ratings, setRatings] = useState({});
const [comments, setComments] = useState({});
// Modal state
const [showModal, setShowModal] = useState(false);
- const [activeSignatureTarget, setActiveSignatureTarget] = useState('advisor');
- const [typedSignatures, setTypedSignatures] = useState({ advisor: '', coordinator: '' });
+ const [activeSignatureTarget, setActiveSignatureTarget] = useState("advisor");
+ const [typedSignatures, setTypedSignatures] = useState({
+ advisor: "",
+ coordinator: "",
+ });
const [selectedFont, setSelectedFont] = useState(fonts[0]);
- const [activeTab, setActiveTab] = useState('type');
+ const [activeTab, setActiveTab] = useState("type");
// Signature canvas ref
const sigCanvasRef = useRef(null);
-
// Clear typed signature if tab switches to "type"
useEffect(() => {
- if (activeTab === 'type') {
- setTypedSignatures(prev => ({ ...prev, [activeSignatureTarget]: '' }));
+ if (activeTab === "type") {
+ setTypedSignatures((prev) => ({ ...prev, [activeSignatureTarget]: "" }));
}
}, [activeSignatureTarget, showModal, activeTab]);
// Handle form input changes
const handleChange = (field, value) => {
- setFormData(prev => ({ ...prev, [field]: value }));
+ setFormData((prev) => ({ ...prev, [field]: value }));
};
// Rating selection
const handleRatingChange = (item, value) => {
- setRatings(prev => ({ ...prev, [item]: value }));
+ setRatings((prev) => ({ ...prev, [item]: value }));
};
// Comment box
const handleCommentChange = (item, value) => {
- setComments(prev => ({ ...prev, [item]: value }));
+ setComments((prev) => ({ ...prev, [item]: value }));
};
// Handle inserting signature from modal
const handleSignatureInsert = () => {
- const targetField = activeSignatureTarget === 'advisor' ? 'advisorSignature' : 'coordinatorSignature';
- if (activeTab === 'type' && typedSignatures[activeSignatureTarget].trim()) {
+ const targetField =
+ activeSignatureTarget === "advisor"
+ ? "advisorSignature"
+ : "coordinatorSignature";
+ if (activeTab === "type" && typedSignatures[activeSignatureTarget].trim()) {
//handleChange(targetField, JSON.stringify({ type: 'text', value: typedSignatures[activeSignatureTarget], font: selectedFont }));
- handleChange(targetField, { type: 'text', value: typedSignatures[activeSignatureTarget], font: selectedFont });
+ handleChange(targetField, {
+ type: "text",
+ value: typedSignatures[activeSignatureTarget],
+ font: selectedFont,
+ });
setShowModal(false);
- } else if (activeTab === 'draw') {
+ } else if (activeTab === "draw") {
const canvas = sigCanvasRef.current;
if (canvas && !canvas.isEmpty()) {
let trimmedCanvas;
@@ -83,9 +107,9 @@ const A3JobEvaluationForm = () => {
console.warn("getTrimmedCanvas() failed, using full canvas instead.");
trimmedCanvas = canvas.getCanvas();
}
- const signatureData = trimmedCanvas.toDataURL('image/png');
+ const signatureData = trimmedCanvas.toDataURL("image/png");
//handleChange(targetField, JSON.stringify({ type: 'draw', value: signatureData }));
- handleChange(targetField, { type: 'draw', value: signatureData })
+ handleChange(targetField, { type: "draw", value: signatureData });
setShowModal(false);
} else {
alert("Please draw your signature before inserting.");
@@ -97,143 +121,319 @@ const A3JobEvaluationForm = () => {
const handleSubmit = async (e) => {
e.preventDefault();
if (!formData.advisorAgreement || !formData.coordinatorAgreement) {
- alert('Please confirm both signature agreements before submitting.');
+ alert("Please confirm both signature agreements before submitting.");
return;
}
try {
- const response = await fetch('http://localhost:5001/api/evaluation', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ formData, ratings, comments }),
- });
+ const response = await fetch(
+ `${process.env.REACT_APP_API_URL}/api/evaluation`,
+ {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ formData, ratings, comments }),
+ }
+ );
if (response.ok) {
- alert('Evaluation submitted successfully!');
- setFormData({ advisorSignature: '', advisorAgreement: false, coordinatorSignature: '', coordinatorAgreement: false });
+ alert("Evaluation submitted successfully!");
+ setFormData({
+ advisorSignature: "",
+ advisorAgreement: false,
+ coordinatorSignature: "",
+ coordinatorAgreement: false,
+ });
setRatings({});
setComments({});
- setTypedSignatures({ advisor: '', coordinator: '' });
+ setTypedSignatures({ advisor: "", coordinator: "" });
sigCanvasRef.current?.clear();
} else {
const err = await response.json();
console.error("Backend returned error:", err);
alert(`Submission failed: ${err.error}`);
- }
+ }
} catch (err) {
- alert('Server error. Please try again.');
+ alert("Server error. Please try again.");
console.error(err);
}
};
-// Show preview of signature (text or image)
-const renderSignaturePreview = (field) => {
+ // Show preview of signature (text or image)
+ const renderSignaturePreview = (field) => {
if (!formData[field]) {
- return Click to sign;
+ return Click to sign;
}
-
+
let sig = formData[field];
- if (typeof sig === 'string') {
+ if (typeof sig === "string") {
try {
sig = JSON.parse(sig);
} catch (err) {
- return Invalid signature format;
+ return Invalid signature format;
}
}
-
- if (sig.type === 'draw') {
- return ;
+
+ if (sig.type === "draw") {
+ return (
+
+ );
}
- if (sig.type === 'text') {
- return {sig.value};
+ if (sig.type === "text") {
+ return (
+
+ {sig.value}
+
+ );
}
-
- return Unknown signature type;
+
+ return Unknown signature type;
};
-
+
return (