add delete modal
All checks were successful
Deploy Amap / deploy (push) Successful in 40s

This commit is contained in:
Julien Aldon
2026-03-06 15:19:07 +01:00
parent e970bb683a
commit 61710a0347
12 changed files with 216 additions and 15 deletions

View File

@@ -84,6 +84,8 @@
"once all contracts downloaded, you can delete the form (to avoid new submissions) and hide it from the home page": "once all contracts downloaded, you can delete the form (to avoid new submissions) and hide it from the home page",
"by checking this option the form will be accessible publicly on the home page, only check it if everything is fine with your form": "by checking this option the form will be accessible publicly on the home page, only check it if everything is fine with your form",
"contracts": "contracts",
"contract": "contract",
"user": "user",
"hidden": "hidden",
"visible": "visible",
"minimum price for this shipment should be at least": "minimum price for this shipment should be at least",
@@ -179,6 +181,10 @@
"grams": "grams (g)",
"kilo": "kilograms (kg)",
"liter": "liters (L)",
"are you sure you want to delete": "are you sure you want to delete",
"this will also delete": "this will also delete",
"delete entity": "delete {{entity}}",
"delete": "delete",
"success": "success",
"success edit": "{{entity}} correctly edited",
"success create": "{{entity}} correctly created",

View File

@@ -81,6 +81,8 @@
"there is": "il y a",
"for this contract": "pour ce contrat.",
"remove shipment": "supprimer la livraison",
"contract": "contrat",
"user": "utilisateur·trice",
"productors": "producteur·trices",
"products": "produits",
"templates": "modèles",
@@ -179,6 +181,10 @@
"grams": "grammes (g)",
"kilo": "kilogrammes (kg)",
"liter": "litres (L)",
"are you sure you want to delete": "êtes vous sûr de vouloir supprimer",
"this will also delete": "cette action supprimera aussi",
"delete entity": "supprimer un {{entity}}",
"delete": "supprimer",
"success": "succès",
"success edit": "{{entity}} correctement édité",
"success create": "{{entity}} correctement créé",

View File

@@ -0,0 +1,76 @@
import { t } from "@/config/i18n";
import type { DeleteDependencies } from "@/services/resources/common";
import { Button, Group, List, Modal, Text, type ModalBaseProps } from "@mantine/core";
import { IconCancel, IconCheck } from "@tabler/icons-react";
import { Link } from "react-router";
export type DeleteModalProps = ModalBaseProps & {
handleSubmit: (id: number) => void;
entityType: string;
entity: {name: string, id: number};
dependencies: DeleteDependencies[];
}
export function DeleteModal({
opened,
onClose,
handleSubmit,
entityType,
entity,
dependencies
}: DeleteModalProps) {
return (
<Modal
opened={opened}
onClose={onClose}
title={t("delete entity", { capfirst: true, entity: t(entityType)})}
>
<Text>{`${t("are you sure you want to delete", {capfirst: true})} : "${entity.name}"`}</Text>
<Text>{`${t("this will also delete", {capfirst: true})} :`}</Text>
{
<List>
{
dependencies?.map((dependency) => (
<List.Item
key={dependency.id}
>
{
dependency.type === 'contract' ? `${t(dependency.type, {capfirst: true})} - ${dependency.name}` :
<Link
to={`/dashboard/${dependency.type}s/${dependency.id}/edit`}
target="_blank"
rel="noopener noreferrer"
>
{`${t(dependency.type, {capfirst: true})} - ${dependency.name}`}
</Link>
}
</List.Item>
))
}
</List>
}
<Group mt="sm" justify="space-between">
<Button
variant="filled"
color="red"
aria-label={t("cancel", { capfirst: true })}
leftSection={<IconCancel />}
onClick={onClose}
>
{t("cancel", { capfirst: true })}
</Button>
<Button
variant="filled"
aria-label={t("delete entity", { capfirst: true, entity: t(entityType)})}
leftSection={<IconCheck />}
onClick={() => {
handleSubmit(entity.id);
}}
>
{t("delete", { capfirst: true})}
</Button>
</Group>
</Modal>
);
}

View File

@@ -1,9 +1,11 @@
import { ActionIcon, Badge, Table, Tooltip } from "@mantine/core";
import { useNavigate, useSearchParams } from "react-router";
import { useDeleteForm } from "@/services/api";
import { useDeleteForm, useGetDeleteDependencies } from "@/services/api";
import { IconEdit, IconX } from "@tabler/icons-react";
import { t } from "@/config/i18n";
import type { Form } from "@/services/resources/forms";
import { DeleteModal } from "@/components/DeleteModal";
import { useDisclosure } from "@mantine/hooks";
export type FormRowProps = {
form: Form;
@@ -13,7 +15,8 @@ export default function FormRow({ form }: FormRowProps) {
const [searchParams] = useSearchParams();
const deleteMutation = useDeleteForm();
const navigate = useNavigate();
const [deleteOpened, { open: deleteOpen, close: deleteClose }] = useDisclosure(false);
const {data: deleteDependencies} = useGetDeleteDependencies("form", form.id);
return (
<Table.Tr key={form.id}>
<Table.Td>
@@ -29,7 +32,7 @@ export default function FormRow({ form }: FormRowProps) {
<Table.Td>{form.productor.name}</Table.Td>
<Table.Td>{form.referer.name}</Table.Td>
<Table.Td>
<Tooltip label={t("edit productor", { capfirst: true })}>
<Tooltip label={t("edit form", { capfirst: true })}>
<ActionIcon
size="sm"
mr="5"
@@ -43,14 +46,22 @@ export default function FormRow({ form }: FormRowProps) {
<IconEdit />
</ActionIcon>
</Tooltip>
<Tooltip label={t("remove productor", { capfirst: true })}>
<DeleteModal
opened={deleteOpened}
onClose={deleteClose}
handleSubmit={(id: number) => {
deleteMutation.mutate(id);
}}
entityType={"form"}
entity={form}
dependencies={deleteDependencies || []}
/>
<Tooltip label={t("remove form", { capfirst: true })}>
<ActionIcon
color="red"
size="sm"
mr="5"
onClick={() => {
deleteMutation.mutate(form.id);
}}
onClick={deleteOpen}
>
<IconX />
</ActionIcon>

View File

@@ -36,12 +36,14 @@ export function Forms() {
const { data: allForms } = useGetReferentForms();
const seasons = useMemo(() => {
if (!allForms) return [];
return allForms
?.map((form: Form) => form.season)
.filter((season, index, array) => array.indexOf(season) === index);
}, [allForms]);
const productors = useMemo(() => {
if (!allForms) return [];
return allForms
?.map((form: Form) => form.productor.name)
.filter((productor, index, array) => array.indexOf(productor) === index);

View File

@@ -151,7 +151,7 @@ export default function Shipments() {
</Table.Tr>
</Table.Thead>
<Table.Tbody>
{shipments.map((shipment) => (
{shipments?.map((shipment) => (
<ShipmentRow shipment={shipment} key={shipment.id} />
))}
</Table.Tbody>

View File

@@ -24,6 +24,7 @@ import type { Product, ProductCreate, ProductEditPayload } from "./resources/pro
import type { Contract, ContractCreate } from "./resources/contracts";
import { notifications } from "@mantine/notifications";
import { t } from "@/config/i18n";
import type { DeleteDependencies, EntityName } from "./resources/common";
export async function refreshToken() {
return await fetch(`${Config.backend_uri}/auth/refresh`, {method: "POST", credentials: "include"});
@@ -321,6 +322,25 @@ export function useGetForm(
});
}
export function useGetDeleteDependencies(
entity: EntityName,
id?: number,
) {
return useQuery<DeleteDependencies[]>({
queryKey: [`${entity}_delete_preview`],
queryFn: () =>
fetchWithAuth(`${Config.backend_uri}/${entity}s/${id}/preview-delete`, {
credentials: "include",
}).then((res) => {
const result = res.json()
console.log(result)
return result
}),
enabled: !!id,
});
}
export function useGetForms(filters?: URLSearchParams): UseQueryResult<Form[], Error> {
const queryString = filters?.toString();
return useQuery<Form[]>({

View File

@@ -0,0 +1,16 @@
export const ENTITY_NAMES = [
'contract',
'form',
'productor',
'product',
'shipment',
'user',
]
export type EntityName = (typeof ENTITY_NAMES)[number];
export type DeleteDependencies = {
name: string;
id: number;
type: EntityName;
}