How about community programmers, I am making a CRUD for a user in which you can enter data such as your name, surname, date of birth and the roles you will have, the latter is done through a checkbox because a user can have multiple roles, I already have the part to save and delete the roles that the user selected but I need the part to edit the roles that he has selected, that is, in the edition the user has two options: add more roles or remove all or just some of the roles you already have. I tried to make it so that when the user clicked on the edit button, all the roles that they already had would be deleted, that is, to do a type of reset so that they could enter their roles again, but I think that this is not very functional at the user experience level, it What I would like to implement is that when editing the checkbox, the roles that the user already has will appear marked and from here if you uncheck any of the checkboxes, save this change and delete that record in the database or if you mark a new checkbox in the database add that new record, in question to the database I have the following tables: user table where the user id, name, surname and date of birth are stored, roles table where the role id and the role name and a third table that serves as a union between the two previous tables where the user id and the role id are stored.
I share the code I have at the moment:
import React, { useEffect, useState } from "react";
import { supabase } from "../supabase/client";
import RegisterFormUser from "./RegisterFormUser";
import SignOut from "./SignOut";
import TableUser from "./TableUser";
const CrudUser = () => {
const [db, setDb] = useState({});
const [dataRol, setDataRol] = useState({});
const [nameRol, setNameRol] = useState([]);
const [dataUserRol, setDataUserRol] = useState({});
const [dataToEdit, setDataToEdit] = useState(null);
const [user, setUser] = useState([]);
const getAuthenticatedUserData = () => {
try {
supabase.auth.getUser().then(async (value) => {
setUser(value.data.user);
});
} catch (error) {
console.error(error.message);
}
};
const getUserData = () => {
try {
supabase.auth.getUser().then(async (value) => {
const user = value.data.user;
const { data } = await supabase
.from("users")
.select()
.eq("email", user.email);
setDb(data);
});
} catch (error) {
console.error(error.message);
}
};
const getRoles = async () => {
try {
const { data } = await supabase.from("roles").select("*");
setDataRol(data);
} catch (error) {
console.error(error);
}
};
const getDataTabRolesUser = async () => {
try {
const { data } = await supabase.from("users_roles").select("*");
setDataUserRol(data);
} catch (error) {
console.error(error.message);
}
};
useEffect(() => {
const getUserRole = async () => {
try {
const { data } = await supabase
.from("users")
.select("roles(nombre)")
.eq("email", user.email);
const auxNameRol = [];
if (data.length > 0) {
data[0].roles.map((el) => auxNameRol.push(el.nombre));
}
setNameRol(auxNameRol);
} catch (error) {
console.log(error.message);
}
};
getUserRole();
}, [dataUserRol, user]);
useEffect(() => {
getUserData();
getRoles();
getDataTabRolesUser();
}, []);
useEffect(() => {
getAuthenticatedUserData();
}, []);
const createDataUser = async (data) => {
try {
data.user_id = Date.now();
await supabase.from("users").insert({
user_id: data.user_id,
email: user.email,
nombres: data.nombres,
apellidos: data.apellidos,
fecha_nacimiento: data.fecha_nacimiento,
is_active: true,
});
console.log("Register added successfully");
setDb([...db, data]);
} catch (error) {
console.error(error.message);
}
};
const createRolesUser = (data) => {
data.roles.map(async (el) => {
await supabase
.from("users_roles")
.insert({ user_id: data.user_id, rol_id: el });
setDataUserRol([...dataUserRol, data]);
});
};
const deleteDataUser = async (id) => {
let isDelete = window.confirm("Are you sure to delete your data?");
if (isDelete) {
try {
await supabase.from("users_roles").delete().eq("user_id", id);
await supabase.from("users").delete().eq("user_id", id);
let newData = db.filter((el) => el.user_id !== id);
setDb(newData);
console.log("The record was deleted");
} catch (error) {
console.error(error.message);
}
} else {
return;
}
};
const deleteRolesUser = async (id) => {
try {
await supabase.from("users_roles").delete().eq("user_id", id);
console.log("Roles eliminados");
let newData = dataUserRol.filter((el) => el.user_id !== id);
setDataUserRol(newData);
} catch (error) {
console.error(error.message);
}
};
const updateDataUser = async (data, updateFields) => {
const { error } = await supabase
.from("users")
.update(updateFields)
.eq("user_id", data.user_id);
let newData = db.map((el) => (el.user_id === data.user_id ? data : el));
setDb(newData);
if (error) throw error;
};
return (
<div>
<div className="grid-1-2">
<RegisterFormUser
data={dataRol}
userData={db}
createDataUser={createDataUser}
createRolesUser={createRolesUser}
dataToEdit={dataToEdit}
updateDataUser={updateDataUser}
setDataToEdit={setDataToEdit}
deleteRolesUser={deleteRolesUser}
/>
<br />
<br />
<TableUser
data={db}
dataRol={nameRol}
setDataToEdit={setDataToEdit}
deleteDataUser={deleteDataUser}
/>
<SignOut />
</div>
</div>
);
};
export default CrudUser;
import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { supabase } from "../supabase/client";
import { v4 as uuidv4 } from "uuid";
import AvatarUser from "./AvatarUser";
const initialForm = {
user_id: null,
nombres: "",
apellidos: "",
fecha_nacimiento: "",
avatar: "",
roles: [],
};
function RegisterFormUser(props) {
//Props
const {
data,
userData,
createDataUser,
createRolesUser,
dataToEdit,
updateDataUser,
//updateRolesUser,
setDataToEdit,
//deleteRolesUser,
} = props;
//States
const [form, setForm] = useState(initialForm);
const [message, setMessage] = useState();
const [response, setResponse] = useState(null);
const [user, setUser] = useState({});
const [selectedRoles, setSelectedRoles] = useState([]);
const navigate = useNavigate();
const getUserData = () => {
supabase.auth.getUser().then(async (valuue) => {
setUser(valuue.data.user);
});
};
useEffect(() => {
getUserData();
}, []);
//Set form Values from dataToEdit
useEffect(() => {
if (dataToEdit) {
setForm(dataToEdit);
} else {
setForm(initialForm);
}
}, [dataToEdit]);
//Redirect to signin if not logged in
useEffect(() => {
supabase.auth.getUser().then((value) => {
if (!value.data.user) {
navigate("/signin");
}
});
}, [navigate]);
//Handle form input changes
const handleChange = (e) => {
setForm({
...form,
[e.target.name]: e.target.value,
});
};
//Handle form submit
const handleSubmit = (e) => {
e.preventDefault();
if (form.user_id === null) {
createDataUser(form);
setMessage("Register added successfully");
setResponse(true);
setTimeout(() => {
setResponse(false);
}, 3000);
setTimeout(() => {
createRolesUser(form);
}, 200);
} else if (form.user_id !== null) {
updateDataUser(form, {
nombres: form.nombres,
apellidos: form.apellidos,
fecha_nacimiento: form.fecha_nacimiento,
});
}
handleReset();
};
//Handle form reset
const handleReset = (e) => {
setForm(initialForm);
setDataToEdit(null);
};
//Handle select changes
const handleCheckboxChange = (e) => {
const roleId = parseInt(e.target.value, 10);
if (e.target.checked) {
setSelectedRoles([...selectedRoles, roleId]);
setForm({
...form,
roles: [...form.roles, roleId],
});
} else {
setSelectedRoles(selectedRoles.filter((id) => id !== roleId));
setForm({
...form,
roles: form.roles.filter((id) => id !== roleId),
});
}
};
//Handle seleccion pictures
const handleSelectPicture = async (e) => {
let file = e.target.files[0];
const { data, error } = await supabase.storage
.from("avatars")
.upload(user.id + "/" + uuidv4(), file);
if (data) {
console.log("success");
} else {
console.log(error);
}
};
return (
<div>
<h1>Additional data</h1>
{dataToEdit || userData.length <= 0 ? (
<form onSubmit={handleSubmit}>
<h3>{dataToEdit ? "Edit" : "Add"}</h3>
<label htmlFor="nombres">Name </label>
<input
type="text"
id="nombres"
name="nombres"
onChange={handleChange}
value={form.nombres}
placeholder="Write your Name"
/>
<br />
<br />
<label htmlFor="apellidos">Last names </label>
<input
type="text"
id="apellidos"
name="apellidos"
onChange={handleChange}
value={form.apellidos}
placeholder="Write your last name"
/>
<br />
<br />
<label htmlFor="fecha_nacimiento">Birthdate </label>
<input
type="date"
id="fecha_nacimiento"
name="fecha_nacimiento"
onChange={handleChange}
value={form.fecha_nacimiento}
/>
<br />
<br />
<label>Select your role: </label>
<br />
<br />
{data.length > 0 ? (
data.map((el, index) => (
<div key={index} className="inline-role">
<input
type="checkbox"
id={`role-${el.roles_id}`}
value={el.roles_id}
name={el.nombre}
checked={selectedRoles.includes(el.roles_id)}
onChange={handleCheckboxChange}
/>
<label htmlFor={`role-${el.roles_id}`}>{el.nombre}</label>
</div>
))
) : (
<p>Loading...</p>
)}
<br />
<br />
<label htmlFor="avatar">Upload an avatar: </label>
<input
type="file"
id="avatar"
name="avatar"
accept=".png, .jpg, .jpeg"
onChange={handleSelectPicture}
/>
<br />
<br />
<AvatarUser dataToEdit={dataToEdit} userData={userData} />
<input type="submit" value={dataToEdit ? "Edit" : "Add Data"} />
<input type="reset" value="Cancel" onClick={handleReset} />
</form>
) : (
<>
<h3>Yor data</h3>
<AvatarUser dataToEdit={dataToEdit} userData={userData} />
</>
)}
{response && <p>{message}</p>}
</div>
);
}
export default RegisterFormUser;
import TableRowUser from "./TableRowUser";
const TableUser = ({ data, dataRol, setDataToEdit, deleteDataUser}) => {
return (
<div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Last names</th>
<th>Birthdate</th>
<th>Rol</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{data.length > 0 ? (
data.map((el) => (
<TableRowUser
key={el.user_id}
el={el}
dataRol={dataRol}
setDataToEdit={setDataToEdit}
deleteDataUser={deleteDataUser}
/>
))
) : (
<tr>
<td colSpan="5">You have not entered additional data</td>
</tr>
)}
</tbody>
</table>
</div>
);
};
export default TableUser;
const TableRowUser = ({ el, dataRol, setDataToEdit, deleteDataUser }) => {
let { user_id, nombres, apellidos, fecha_nacimiento} = el;
return (
<tr>
<td>{nombres}</td>
<td>{apellidos}</td>
<td>{fecha_nacimiento}</td>
{dataRol.length > 0 ? <td>{dataRol.join(", ")}</td> : <td>empty data</td>}
<td>
<button onClick={() => setDataToEdit(el)}>Edit</button>
<button onClick={() => deleteDataUser(user_id)}>Delete</button>
</td>
</tr>
);
};
export default TableRowUser;