im on a Laravel/Nextjs project.
Im retrieving data so the user can edit if he wish.
After several tries, i've managed to show the data on the form, and i can edit the input name, and select different degrees.
The problem is with the checkbox input, when i try to deselect it does it in order and not by the one i've clicked on it. + I can't select more than 1 checkbox.
I will show you the component, the form component and the data i get from the backend.
Any information would help me a lot. Thanks !
"use client";
import { useEffect, useState } from "react";
import axios from "axios";
import { useSnackbar } from "notistack";
import { useParams, useRouter } from "next/navigation";
import Form from "@/app/form";
import Header from "@/app/Admin/header";
export default function EditYear() {
const { enqueueSnackbar } = useSnackbar();
const router = useRouter();
const { id } = useParams();
const backendURL = process.env.NEXT_PUBLIC_BACKEND_URL;
const token =
typeof window !== "undefined" ? localStorage.getItem("auth_token") : null;
const type =
typeof window !== "undefined" ? localStorage.getItem("type") : null;
const [yearData, setYearData] = useState({});
const [degrees, setDegrees] = useState([]);
const [selectedDegree, setSelectedDegree] = useState("");
const [selectedSubjects, setSelectedSubjects] = useState([]);
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get(
`${backendURL}/api/year/edit/${id}`,
{
headers: {
Authorization: `Bearer ${token}`,
"X-Type": type,
},
}
);
if (response.status === 200) {
const data = response.data;
setYearData(data.year_data);
setDegrees(data.degrees);
setSelectedDegree(data.year_data.degree_id);
setSelectedSubjects(data.year_data.subjects.map((subject) => subject.id));
} else {
console.error("Error: Unable to fetch data");
}
} catch (error) {
console.error("Error: ", error.message);
}
};
fetchData();
}, []);
const handleFormSubmit = async (e) => {
e.preventDefault();
// Your form submission logic here
};
const handleInputChange = (e) => {
// Update the form field value based on the input name
const { name, value } = e.target;
setYearData((prevData) => ({
...prevData,
[name]: value,
}));
};
const handleDegreeChange = (e) => {
// Update the selected degree value
const selectedDegreeId = parseInt(e.target.value);
setSelectedDegree(selectedDegreeId);
// Filter and update the selected subjects based on the selected degree
const selectedDegree = degrees.find((degree) => degree.id === selectedDegreeId);
setSelectedSubjects(selectedDegree ? selectedDegree.subjects.map((subject) => subject.id) : []);
};
const handleSubjectChange = (e) => {
// Update the selected subjects array
const selectedSubjectId = parseInt(e.target.value);
setSelectedSubjects((prevSubjects) =>
prevSubjects.includes(selectedSubjectId)
? prevSubjects.filter((id) => id !== selectedSubjectId)
: [...prevSubjects, selectedSubjectId]
);
};
const fields = [
{
label: "Name",
type: "text",
name: "year_name",
value: yearData.year_name || "",
onChange: handleInputChange,
},
{
label: "Degree",
type: "select",
name: "degree_id",
value: selectedDegree,
options: degrees.map((degree) => ({
label: degree.name,
value: degree.id,
})),
onChange: handleDegreeChange,
},
{
label: "Subjects",
type: "checkbox",
name: "subjects",
options: degrees
.find((degree) => degree.id === selectedDegree)
?.subjects.map((subject) => ({
label: subject.name,
value: subject.id,
})) || [],
value: selectedSubjects,
onChange: handleSubjectChange,
},
];
return (
<>
<Header title="Create Year" />
<Form
onSubmit={handleFormSubmit}
fields={fields}
type="Create Year"
send="Add a Year"
/>
</>
);
}
Here is the form.
export default function Form({ onSubmit, fields, type, send, initialValue }) {
const handleCheckboxChange = (e, field) => {
const { value, checked } = e.target;
field.onChange({
target: {
name: field.name,
value: checked
? [...field.value, value]
: field.value.filter((item) => item !== value),
},
});
};
return (
<div className="flex flex-col w-4/5 h-auto p-4 mx-auto my-0 lg:shadow-none gap-y-4 lg:w-2/3">
<div className="text-lg font-semibold uppercase lg:text-xl">
<h1>{type}</h1>
</div>
<form className="flex flex-col lg:gap-y-4 gap-y-6" onSubmit={onSubmit}>
{fields.map((field) => (
<div key={field.name} className="flex flex-col gap-y-2">
<label className="text-sm lg:text-base">{field.label}</label>
{field.type === "checkbox" ? (
field.options.map((option) => (
<div key={option.value} className="flex items-center">
<input
className="mr-2"
type="checkbox"
name={field.name}
value={option.value}
checked={field.value.includes(option.value)}
onChange={(e) => handleCheckboxChange(e, field)}
/>
<label>{option.label}</label>
</div>
))
) : field.type === "select" ? (
<select
className="h-8 pl-4 border-2 border-gray-500 border-solid rounded-md outline-none focus:border-verde lg:h-12"
name={field.name}
value={field.value}
onChange={field.onChange}
>
<option value="">{initialValue}</option>
{field.options.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
) : (
<input
className="h-8 pl-4 border-2 border-gray-500 border-solid rounded-md outline-none focus:border-verde lg:h-12"
placeholder={field.placeholder}
type={field.type}
name={field.name}
value={field.value}
onChange={field.onChange}
/>
)}
</div>
))}
<button
type="submit"
className="flex items-center justify-center w-1/2 h-10 mx-auto my-0 text-sm font-medium text-white transition-colors duration-300 rounded-lg lg:w-1/4 bg-verde hover:bg-green-500 focus:outline-none focus:ring-2 focus:ring-green-500 active:bg-green-700"
>
{send}
</button>
</form>
</div>
);
}
And the data in json.
{
"year_data": {
"year_id": 2,
"year_name": "Medicina-2",
"degree_id": 1,
"degree_name": "Medicinal",
"subjects": []
},
"degrees": [
{
"id": 1,
"branch_id": 1,
"name": "Medicinal",
"created_at": "2023-06-25T16:43:51.000000Z",
"updated_at": "2023-07-10T09:28:42.000000Z",
"subjects": [
{
"id": 6,
"degree_id": 1,
"name": "Aniouno",
"created_at": "2023-07-20T22:06:08.000000Z",
"updated_at": "2023-07-20T22:06:08.000000Z"
},
{
"id": 7,
"degree_id": 1,
"name": "anio2",
"created_at": "2023-07-20T22:06:08.000000Z",
"updated_at": "2023-07-20T22:06:08.000000Z"
},
{
"id": 8,
"degree_id": 1,
"name": "mok",
"created_at": "2023-07-20T22:06:08.000000Z",
"updated_at": "2023-07-20T22:06:08.000000Z"
},
{
"id": 9,
"degree_id": 1,
"name": "bok",
"created_at": "2023-07-20T22:06:08.000000Z",
"updated_at": "2023-07-20T22:06:08.000000Z"
}
]
},
{
"id": 8,
"branch_id": 1,
"name": "Anatomias",
"created_at": "2023-07-10T05:52:52.000000Z",
"updated_at": "2023-07-10T05:52:52.000000Z",
"subjects": [
{
"id": 2,
"degree_id": 8,
"name": "Dentistas",
"created_at": "2023-06-25T16:50:45.000000Z",
"updated_at": "2023-07-11T11:04:44.000000Z"
}
]
},
{
"id": 9,
"branch_id": 1,
"name": "Aeroplanes",
"created_at": "2023-07-10T05:52:52.000000Z",
"updated_at": "2023-07-10T05:52:52.000000Z",
"subjects": []
},
{
"id": 10,
"branch_id": 1,
"name": "Arquitectura",
"created_at": "2023-07-10T05:52:52.000000Z",
"updated_at": "2023-07-10T05:52:52.000000Z",
"subjects": [
{
"id": 4,
"degree_id": 10,
"name": "Ahorasi",
"created_at": "2023-06-25T16:50:45.000000Z",
"updated_at": "2023-07-11T11:04:32.000000Z"
}
]
}
]
}
Aucun commentaire:
Enregistrer un commentaire