This commit is contained in:
@@ -24,3 +24,6 @@
|
|||||||
### Show on cascade deletion
|
### Show on cascade deletion
|
||||||
|
|
||||||
## Update contract after (without registration)
|
## Update contract after (without registration)
|
||||||
|
|
||||||
|
## Preview form (if not visible can be accessed by referer nothing is stored)
|
||||||
|
## View and edit contract application (dashboard/contracts/id/edit/)
|
||||||
|
|||||||
@@ -196,6 +196,24 @@ def get_contract_file(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get(
|
||||||
|
'/{_id}/preview-delete',
|
||||||
|
response_model=list[models.DeleteDependency]
|
||||||
|
)
|
||||||
|
async def preview_delete(
|
||||||
|
_id: int,
|
||||||
|
session: Session = Depends(get_session),
|
||||||
|
user: models.User = Depends(get_current_user),
|
||||||
|
):
|
||||||
|
if not service.is_allowed(session, user, _id=_id):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=403,
|
||||||
|
detail=messages.Messages.not_allowed('contract', 'delete')
|
||||||
|
)
|
||||||
|
result = []
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
@router.get('/{form_id}/files')
|
@router.get('/{form_id}/files')
|
||||||
def get_contract_files(
|
def get_contract_files(
|
||||||
form_id: int,
|
form_id: int,
|
||||||
|
|||||||
@@ -18,6 +18,30 @@ def get_productors(
|
|||||||
return service.get_all(session, user, names, types)
|
return service.get_all(session, user, names, types)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get(
|
||||||
|
'/{_id}/preview-delete',
|
||||||
|
response_model=list[models.DeleteDependency]
|
||||||
|
)
|
||||||
|
async def preview_delete(
|
||||||
|
_id: int,
|
||||||
|
session: Session = Depends(get_session),
|
||||||
|
user: models.User = Depends(get_current_user),
|
||||||
|
):
|
||||||
|
if not service.is_allowed(session, user, _id=_id):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=403,
|
||||||
|
detail=messages.Messages.not_allowed('productors', 'delete')
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
result = service.get_delete_dependencies(
|
||||||
|
session,
|
||||||
|
_id
|
||||||
|
)
|
||||||
|
except exceptions.ProductorNotFoundError as error:
|
||||||
|
raise HTTPException(status_code=404, detail=str(error)) from error
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
@router.get('/{_id}', response_model=models.ProductorPublic)
|
@router.get('/{_id}', response_model=models.ProductorPublic)
|
||||||
def get_productor(
|
def get_productor(
|
||||||
_id: int,
|
_id: int,
|
||||||
|
|||||||
@@ -93,6 +93,33 @@ def delete_one(session: Session, _id: int) -> models.ProductorPublic:
|
|||||||
session.commit()
|
session.commit()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def get_delete_dependencies(
|
||||||
|
session: Session,
|
||||||
|
_id: int
|
||||||
|
) -> list[models.DeleteDependency]:
|
||||||
|
statement = select(models.Productor).where(models.Productor.id == _id)
|
||||||
|
result = session.exec(statement)
|
||||||
|
productor = result.first()
|
||||||
|
if not productor:
|
||||||
|
raise exceptions.ProductorNotFoundError(
|
||||||
|
messages.Messages.not_found('productor'))
|
||||||
|
products_statement = (
|
||||||
|
select(models.Product)
|
||||||
|
.where(models.Product.productor_id == _id)
|
||||||
|
.distinct()
|
||||||
|
)
|
||||||
|
products = session.exec(products_statement).all()
|
||||||
|
result = [
|
||||||
|
models.DeleteDependency(
|
||||||
|
name=pro.name,
|
||||||
|
id=pro.id,
|
||||||
|
type='product'
|
||||||
|
) for pro in products
|
||||||
|
]
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def is_allowed(
|
def is_allowed(
|
||||||
session: Session,
|
session: Session,
|
||||||
user: models.User,
|
user: models.User,
|
||||||
|
|||||||
@@ -26,6 +26,23 @@ def get_products(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get(
|
||||||
|
'/{_id}/preview-delete',
|
||||||
|
response_model=list[models.DeleteDependency]
|
||||||
|
)
|
||||||
|
async def preview_delete(
|
||||||
|
_id: int,
|
||||||
|
session: Session = Depends(get_session),
|
||||||
|
user: models.User = Depends(get_current_user),
|
||||||
|
):
|
||||||
|
if not service.is_allowed(session, user, _id=_id):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=403,
|
||||||
|
detail=messages.Messages.not_allowed('product', 'delete')
|
||||||
|
)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
@router.get('/{_id}', response_model=models.ProductPublic)
|
@router.get('/{_id}', response_model=models.ProductPublic)
|
||||||
def get_product(
|
def get_product(
|
||||||
_id: int,
|
_id: int,
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ def delete_one(
|
|||||||
session.commit()
|
session.commit()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def is_allowed(
|
def is_allowed(
|
||||||
session: Session,
|
session: Session,
|
||||||
user: models.User,
|
user: models.User,
|
||||||
@@ -103,12 +104,8 @@ def is_allowed(
|
|||||||
return False
|
return False
|
||||||
if not _id:
|
if not _id:
|
||||||
statement = (
|
statement = (
|
||||||
select(models.Product)
|
select(models.Productor)
|
||||||
.join(
|
.where(models.Productor.id == product.productor_id)
|
||||||
models.Productor,
|
|
||||||
models.Product.productor_id == models.Productor.id
|
|
||||||
)
|
|
||||||
.where(models.Product.id == product.productor_id)
|
|
||||||
)
|
)
|
||||||
productor = session.exec(statement).first()
|
productor = session.exec(statement).first()
|
||||||
return productor.type in [r.name for r in user.roles]
|
return productor.type in [r.name for r in user.roles]
|
||||||
|
|||||||
@@ -26,6 +26,23 @@ def get_shipments(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get(
|
||||||
|
'/{_id}/preview-delete',
|
||||||
|
response_model=list[models.DeleteDependency]
|
||||||
|
)
|
||||||
|
async def preview_delete(
|
||||||
|
_id: int,
|
||||||
|
session: Session = Depends(get_session),
|
||||||
|
user: models.User = Depends(get_current_user),
|
||||||
|
):
|
||||||
|
if not service.is_allowed(session, user, _id=_id):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=403,
|
||||||
|
detail=messages.Messages.not_allowed('shipment', 'delete')
|
||||||
|
)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
@router.get('/{_id}', response_model=models.ShipmentPublic)
|
@router.get('/{_id}', response_model=models.ShipmentPublic)
|
||||||
def get_shipment(
|
def get_shipment(
|
||||||
_id: int,
|
_id: int,
|
||||||
|
|||||||
@@ -36,6 +36,22 @@ def get_roles(
|
|||||||
return service.get_roles(session)
|
return service.get_roles(session)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get(
|
||||||
|
'/{_id}/preview-delete',
|
||||||
|
response_model=list[models.DeleteDependency]
|
||||||
|
)
|
||||||
|
async def preview_delete(
|
||||||
|
_id: int,
|
||||||
|
user: models.User = Depends(get_current_user),
|
||||||
|
):
|
||||||
|
if not service.is_allowed(user):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=403,
|
||||||
|
detail=messages.Messages.not_allowed('user', 'delete')
|
||||||
|
)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
@router.get('/{_id}', response_model=models.UserPublic)
|
@router.get('/{_id}', response_model=models.UserPublic)
|
||||||
def get_user(
|
def get_user(
|
||||||
_id: int,
|
_id: int,
|
||||||
|
|||||||
@@ -39,6 +39,10 @@
|
|||||||
"create productor": "create producer",
|
"create productor": "create producer",
|
||||||
"edit productor": "edit producer",
|
"edit productor": "edit producer",
|
||||||
"remove productor": "remove producer",
|
"remove productor": "remove producer",
|
||||||
|
"remove form": "remove form",
|
||||||
|
"edit shipment": "edit shipment",
|
||||||
|
"create shipment": "create shipment",
|
||||||
|
"create user": "create user",
|
||||||
"home": "home",
|
"home": "home",
|
||||||
"dashboard": "dashboard",
|
"dashboard": "dashboard",
|
||||||
"filter by name": "filter by name",
|
"filter by name": "filter by name",
|
||||||
|
|||||||
@@ -39,6 +39,10 @@
|
|||||||
"create productor": "créer le/la producteur·trice",
|
"create productor": "créer le/la producteur·trice",
|
||||||
"edit productor": "modifier le/la producteur·trice",
|
"edit productor": "modifier le/la producteur·trice",
|
||||||
"remove productor": "supprimer le/la producteur·trice",
|
"remove productor": "supprimer le/la producteur·trice",
|
||||||
|
"remove form": "supprimer un formulaire de contrat",
|
||||||
|
"edit shipment": "modifier la livraison",
|
||||||
|
"create shipment": "créer la livraison",
|
||||||
|
"create user": "créer l'utilisateur·trice",
|
||||||
"home": "accueil",
|
"home": "accueil",
|
||||||
"dashboard": "tableau de bord",
|
"dashboard": "tableau de bord",
|
||||||
"filter by name": "filtrer par nom",
|
"filter by name": "filtrer par nom",
|
||||||
@@ -183,7 +187,7 @@
|
|||||||
"liter": "litres (L)",
|
"liter": "litres (L)",
|
||||||
"are you sure you want to delete": "êtes vous sûr de vouloir supprimer",
|
"are you sure you want to delete": "êtes vous sûr de vouloir supprimer",
|
||||||
"this will also delete": "cette action supprimera aussi",
|
"this will also delete": "cette action supprimera aussi",
|
||||||
"delete entity": "supprimer un {{entity}}",
|
"delete entity": "supprimer le/la {{entity}}",
|
||||||
"delete": "supprimer",
|
"delete": "supprimer",
|
||||||
"success": "succès",
|
"success": "succès",
|
||||||
"success edit": "{{entity}} correctement édité",
|
"success edit": "{{entity}} correctement édité",
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ import { ActionIcon, Table, Tooltip } from "@mantine/core";
|
|||||||
import { type Contract } from "@/services/resources/contracts";
|
import { type Contract } from "@/services/resources/contracts";
|
||||||
import { IconDownload, IconX } from "@tabler/icons-react";
|
import { IconDownload, IconX } from "@tabler/icons-react";
|
||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import { useDeleteContract, useGetContractFile } from "@/services/api";
|
import { useGetContractFile } from "@/services/api";
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
|
import { useNavigate } from "react-router";
|
||||||
|
|
||||||
export type ContractRowProps = {
|
export type ContractRowProps = {
|
||||||
contract: Contract;
|
contract: Contract;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ContractRow({ contract }: ContractRowProps) {
|
export default function ContractRow({ contract }: ContractRowProps) {
|
||||||
const deleteMutation = useDeleteContract();
|
|
||||||
const getContractMutation = useGetContractFile();
|
const getContractMutation = useGetContractFile();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handleDownload = useCallback(async () => {
|
const handleDownload = useCallback(async () => {
|
||||||
getContractMutation.mutateAsync(contract.id);
|
getContractMutation.mutateAsync(contract.id);
|
||||||
@@ -29,12 +30,10 @@ export default function ContractRow({ contract }: ContractRowProps) {
|
|||||||
{contract.cheque_quantity > 0 && contract.cheque_quantity} {contract.payment_method}
|
{contract.cheque_quantity > 0 && contract.cheque_quantity} {contract.payment_method}
|
||||||
</Table.Td>
|
</Table.Td>
|
||||||
<Table.Td>
|
<Table.Td>
|
||||||
{
|
{`${Intl.NumberFormat("fr-FR", {
|
||||||
`${Intl.NumberFormat("fr-FR", {
|
style: "currency",
|
||||||
style: "currency",
|
currency: "EUR",
|
||||||
currency: "EUR",
|
}).format(contract.total_price)}`}
|
||||||
}).format(contract.total_price)}`
|
|
||||||
}
|
|
||||||
</Table.Td>
|
</Table.Td>
|
||||||
<Table.Td>
|
<Table.Td>
|
||||||
<Tooltip label={t("download contract", { capfirst: true })}>
|
<Tooltip label={t("download contract", { capfirst: true })}>
|
||||||
@@ -54,8 +53,9 @@ export default function ContractRow({ contract }: ContractRowProps) {
|
|||||||
color="red"
|
color="red"
|
||||||
size="sm"
|
size="sm"
|
||||||
mr="5"
|
mr="5"
|
||||||
onClick={() => {
|
onClick={(e) => {
|
||||||
deleteMutation.mutate(contract.id);
|
e.stopPropagation();
|
||||||
|
navigate(`/dashboard/contracts/${contract.id}/delete`);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconX />
|
<IconX />
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import { Link } from "react-router";
|
|||||||
export type DeleteModalProps = ModalBaseProps & {
|
export type DeleteModalProps = ModalBaseProps & {
|
||||||
handleSubmit: (id: number) => void;
|
handleSubmit: (id: number) => void;
|
||||||
entityType: string;
|
entityType: string;
|
||||||
entity?: {name: string, id: number} | undefined;
|
entity?: { name: string; id: number } | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
export function DeleteModal({
|
export function DeleteModal({
|
||||||
opened,
|
opened,
|
||||||
@@ -18,39 +18,37 @@ export function DeleteModal({
|
|||||||
entity,
|
entity,
|
||||||
}: DeleteModalProps) {
|
}: DeleteModalProps) {
|
||||||
if (!entity) {
|
if (!entity) {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
const {data: deleteDependencies} = useGetDeleteDependencies(entityType, entity.id);
|
const { data: deleteDependencies } = useGetDeleteDependencies(entityType, entity.id);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
opened={opened}
|
opened={opened}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
title={t("delete entity", { capfirst: true, entity: t(entityType)})}
|
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("are you sure you want to delete", { capfirst: true })} : "${entity.name}"`}</Text>
|
||||||
{deleteDependencies && deleteDependencies.length > 0 ? <Text>{`${t("this will also delete", {capfirst: true})} :`}</Text> : null}
|
{deleteDependencies && deleteDependencies.length > 0 ? (
|
||||||
|
<Text>{`${t("this will also delete", { capfirst: true })} :`}</Text>
|
||||||
|
) : null}
|
||||||
{
|
{
|
||||||
<List>
|
<List>
|
||||||
{
|
{deleteDependencies?.map((dependency) => (
|
||||||
deleteDependencies?.map((dependency) => (
|
<List.Item key={dependency.id}>
|
||||||
<List.Item
|
{dependency.type === "contract" ? (
|
||||||
key={dependency.id}
|
`${t(dependency.type, { capfirst: true })} - ${dependency.name}`
|
||||||
>
|
) : (
|
||||||
{
|
<Link
|
||||||
dependency.type === 'contract' ? `${t(dependency.type, {capfirst: true})} - ${dependency.name}` :
|
to={`/dashboard/${dependency.type}s/${dependency.id}/edit`}
|
||||||
<Link
|
target="_blank"
|
||||||
to={`/dashboard/${dependency.type}s/${dependency.id}/edit`}
|
rel="noopener noreferrer"
|
||||||
target="_blank"
|
>
|
||||||
rel="noopener noreferrer"
|
{`${t(dependency.type, { capfirst: true })} - ${dependency.name}`}
|
||||||
>
|
</Link>
|
||||||
{`${t(dependency.type, {capfirst: true})} - ${dependency.name}`}
|
)}
|
||||||
</Link>
|
</List.Item>
|
||||||
|
))}
|
||||||
}
|
|
||||||
</List.Item>
|
|
||||||
))
|
|
||||||
}
|
|
||||||
</List>
|
</List>
|
||||||
}
|
}
|
||||||
<Group mt="sm" justify="space-between">
|
<Group mt="sm" justify="space-between">
|
||||||
@@ -65,14 +63,14 @@ export function DeleteModal({
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
variant="filled"
|
variant="filled"
|
||||||
aria-label={t("delete entity", { capfirst: true, entity: t(entityType)})}
|
aria-label={t("delete entity", { capfirst: true, entity: t(entityType) })}
|
||||||
leftSection={<IconCheck />}
|
leftSection={<IconCheck />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleSubmit(entity.id);
|
handleSubmit(entity.id);
|
||||||
onClose();
|
onClose();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("delete", { capfirst: true})}
|
{t("delete", { capfirst: true })}
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -10,37 +10,33 @@ export type FormCardProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function FormCard({ form }: FormCardProps) {
|
export function FormCard({ form }: FormCardProps) {
|
||||||
const contractBaseTemplate = useGetContractFileTemplate()
|
const contractBaseTemplate = useGetContractFileTemplate();
|
||||||
return (
|
return (
|
||||||
<Paper shadow="xl" p="xl" miw={{ base: "100vw", md: "25vw", lg: "20vw" }}>
|
<Paper shadow="xl" p="xl" miw={{ base: "100vw", md: "25vw", lg: "20vw" }}>
|
||||||
<Group justify="start" mb="md">
|
<Group justify="start" mb="md">
|
||||||
<Tooltip
|
<Tooltip label={t("download base template to print")}>
|
||||||
label={t("download base template to print")}
|
<ActionIcon
|
||||||
>
|
variant={"outline"}
|
||||||
<ActionIcon
|
aria-label={t("download base template to print")}
|
||||||
variant={"outline"}
|
onClick={async () => {
|
||||||
aria-label={t("download base template to print")}
|
await contractBaseTemplate.mutateAsync(form.id);
|
||||||
onClick={async () => {
|
}}
|
||||||
await contractBaseTemplate.mutateAsync(form.id)
|
>
|
||||||
}}
|
<IconDownload />
|
||||||
>
|
</ActionIcon>
|
||||||
<IconDownload/>
|
</Tooltip>
|
||||||
</ActionIcon>
|
<Tooltip label={t("fill contract online")}>
|
||||||
</Tooltip>
|
<ActionIcon
|
||||||
<Tooltip
|
variant={"outline"}
|
||||||
label={t("fill contract online")}
|
aria-label={t("fill contract online")}
|
||||||
>
|
component={Link}
|
||||||
<ActionIcon
|
to={`/form/${form.id}`}
|
||||||
variant={"outline"}
|
target="_blank"
|
||||||
aria-label={t("fill contract online")}
|
rel="noopener noreferrer"
|
||||||
component={Link}
|
>
|
||||||
to={`/form/${form.id}`}
|
<IconExternalLink />
|
||||||
target="_blank"
|
</ActionIcon>
|
||||||
rel="noopener noreferrer"
|
</Tooltip>
|
||||||
>
|
|
||||||
<IconExternalLink/>
|
|
||||||
</ActionIcon>
|
|
||||||
</Tooltip>
|
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default function FormModal({ opened, onClose, currentForm, handleSubmit }
|
|||||||
productor_id: currentForm?.productor?.id.toString() ?? "",
|
productor_id: currentForm?.productor?.id.toString() ?? "",
|
||||||
referer_id: currentForm?.referer?.id.toString() ?? "",
|
referer_id: currentForm?.referer?.id.toString() ?? "",
|
||||||
minimum_shipment_value: currentForm?.minimum_shipment_value ?? null,
|
minimum_shipment_value: currentForm?.minimum_shipment_value ?? null,
|
||||||
visible: currentForm?.visible ?? false
|
visible: currentForm?.visible ?? false,
|
||||||
},
|
},
|
||||||
validate: {
|
validate: {
|
||||||
name: (value) =>
|
name: (value) =>
|
||||||
@@ -53,8 +53,7 @@ export default function FormModal({ opened, onClose, currentForm, handleSubmit }
|
|||||||
});
|
});
|
||||||
|
|
||||||
const usersSelect = useMemo(() => {
|
const usersSelect = useMemo(() => {
|
||||||
if (!users)
|
if (!users) return [];
|
||||||
return [];
|
|
||||||
return users?.map((user) => ({
|
return users?.map((user) => ({
|
||||||
value: String(user.id),
|
value: String(user.id),
|
||||||
label: `${user.name}`,
|
label: `${user.name}`,
|
||||||
@@ -62,8 +61,7 @@ export default function FormModal({ opened, onClose, currentForm, handleSubmit }
|
|||||||
}, [users]);
|
}, [users]);
|
||||||
|
|
||||||
const productorsSelect = useMemo(() => {
|
const productorsSelect = useMemo(() => {
|
||||||
if (!productors)
|
if (!productors) return [];
|
||||||
return [];
|
|
||||||
return productors?.map((prod) => ({
|
return productors?.map((prod) => ({
|
||||||
value: String(prod.id),
|
value: String(prod.id),
|
||||||
label: `${prod.name}`,
|
label: `${prod.name}`,
|
||||||
@@ -142,10 +140,14 @@ export default function FormModal({ opened, onClose, currentForm, handleSubmit }
|
|||||||
radius="sm"
|
radius="sm"
|
||||||
{...form.getInputProps("minimum_shipment_value")}
|
{...form.getInputProps("minimum_shipment_value")}
|
||||||
/>
|
/>
|
||||||
<Checkbox mt="lg"
|
<Checkbox
|
||||||
label={t("visible", {capfirst: true})}
|
mt="lg"
|
||||||
description={t("by checking this option the form will be accessible publicly on the home page, only check it if everything is fine with your form", {capfirst: true})}
|
label={t("visible", { capfirst: true })}
|
||||||
{...form.getInputProps("visible", {type: "checkbox"})}
|
description={t(
|
||||||
|
"by checking this option the form will be accessible publicly on the home page, only check it if everything is fine with your form",
|
||||||
|
{ capfirst: true },
|
||||||
|
)}
|
||||||
|
{...form.getInputProps("visible", { type: "checkbox" })}
|
||||||
/>
|
/>
|
||||||
<Group mt="sm" justify="space-between">
|
<Group mt="sm" justify="space-between">
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { IconEdit, IconX } from "@tabler/icons-react";
|
|||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import type { Form } from "@/services/resources/forms";
|
import type { Form } from "@/services/resources/forms";
|
||||||
|
|
||||||
|
|
||||||
export type FormRowProps = {
|
export type FormRowProps = {
|
||||||
form: Form;
|
form: Form;
|
||||||
};
|
};
|
||||||
@@ -15,10 +14,11 @@ export default function FormRow({ form }: FormRowProps) {
|
|||||||
return (
|
return (
|
||||||
<Table.Tr key={form.id}>
|
<Table.Tr key={form.id}>
|
||||||
<Table.Td>
|
<Table.Td>
|
||||||
{form.visible ?
|
{form.visible ? (
|
||||||
<Badge color="green">{t("visible", {capfirst: true})}</Badge> :
|
<Badge color="green">{t("visible", { capfirst: true })}</Badge>
|
||||||
<Badge color="red">{t("hidden", {capfirst: true})}</Badge>
|
) : (
|
||||||
}
|
<Badge color="red">{t("hidden", { capfirst: true })}</Badge>
|
||||||
|
)}
|
||||||
</Table.Td>
|
</Table.Td>
|
||||||
<Table.Td>{form.name}</Table.Td>
|
<Table.Td>{form.name}</Table.Td>
|
||||||
<Table.Td>{form.season}</Table.Td>
|
<Table.Td>{form.season}</Table.Td>
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ export function Navbar() {
|
|||||||
<nav>
|
<nav>
|
||||||
<Group>
|
<Group>
|
||||||
<NavLink className={"navLink"} aria-label={t("home")} to="/">
|
<NavLink className={"navLink"} aria-label={t("home")} to="/">
|
||||||
{isPhone ? <IconHome/> : t("home", { capfirst: true })}
|
{isPhone ? <IconHome /> : t("home", { capfirst: true })}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
{user?.logged ? (
|
{user?.logged ? (
|
||||||
<NavLink className={"navLink"} aria-label={t("dashboard")} to="/dashboard/help">
|
<NavLink className={"navLink"} aria-label={t("dashboard")} to="/dashboard/help">
|
||||||
{isPhone ? <IconSettings/> : t("dashboard", { capfirst: true })}
|
{isPhone ? <IconSettings /> : t("dashboard", { capfirst: true })}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
) : null}
|
) : null}
|
||||||
</Group>
|
</Group>
|
||||||
@@ -37,7 +37,7 @@ export function Navbar() {
|
|||||||
className={"navLink"}
|
className={"navLink"}
|
||||||
aria-label={t("login with keycloak", { capfirst: true })}
|
aria-label={t("login with keycloak", { capfirst: true })}
|
||||||
>
|
>
|
||||||
{isPhone ? <IconLogin/> : t("login with keycloak", { capfirst: true })}
|
{isPhone ? <IconLogin /> : t("login with keycloak", { capfirst: true })}
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
<a
|
<a
|
||||||
@@ -45,7 +45,7 @@ export function Navbar() {
|
|||||||
className={"navLink"}
|
className={"navLink"}
|
||||||
aria-label={t("logout", { capfirst: true })}
|
aria-label={t("logout", { capfirst: true })}
|
||||||
>
|
>
|
||||||
{isPhone ? <IconLogout/> : t("logout", { capfirst: true })}
|
{isPhone ? <IconLogout /> : t("logout", { capfirst: true })}
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export function ContractCheque({ inputForm, price, productor }: ContractChequePr
|
|||||||
}, [inputForm.values.cheque_quantity, price, inputForm.values.cheques]);
|
}, [inputForm.values.cheque_quantity, price, inputForm.values.cheques]);
|
||||||
|
|
||||||
const paymentMethod = useMemo(() => {
|
const paymentMethod = useMemo(() => {
|
||||||
return productor?.payment_methods.find((el) => el.name === "cheque")
|
return productor?.payment_methods.find((el) => el.name === "cheque");
|
||||||
}, [productor]);
|
}, [productor]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -57,7 +57,9 @@ export function ContractCheque({ inputForm, price, productor }: ContractChequePr
|
|||||||
{ capfirst: true },
|
{ capfirst: true },
|
||||||
)}
|
)}
|
||||||
min={1}
|
min={1}
|
||||||
max={paymentMethod?.max && paymentMethod?.max !== "" ? Number(paymentMethod?.max) : 3}
|
max={
|
||||||
|
paymentMethod?.max && paymentMethod?.max !== "" ? Number(paymentMethod?.max) : 3
|
||||||
|
}
|
||||||
{...inputForm.getInputProps(`cheque_quantity`)}
|
{...inputForm.getInputProps(`cheque_quantity`)}
|
||||||
/>
|
/>
|
||||||
<Group grow>
|
<Group grow>
|
||||||
@@ -67,11 +69,7 @@ export function ContractCheque({ inputForm, price, productor }: ContractChequePr
|
|||||||
label={t("cheque id", { capfirst: true })}
|
label={t("cheque id", { capfirst: true })}
|
||||||
placeholder={t("cheque id", { capfirst: true })}
|
placeholder={t("cheque id", { capfirst: true })}
|
||||||
{...inputForm.getInputProps(`cheques.${index}.name`)}
|
{...inputForm.getInputProps(`cheques.${index}.name`)}
|
||||||
error={
|
error={cheque.name == "" ? inputForm?.errors.cheques : null}
|
||||||
cheque.name == "" ?
|
|
||||||
inputForm?.errors.cheques :
|
|
||||||
null
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<NumberInput
|
<NumberInput
|
||||||
readOnly
|
readOnly
|
||||||
|
|||||||
@@ -49,20 +49,30 @@ export function ProductorModal({
|
|||||||
type: (value) =>
|
type: (value) =>
|
||||||
!value ? `${t("type", { capfirst: true })} ${t("is required")}` : null,
|
!value ? `${t("type", { capfirst: true })} ${t("is required")}` : null,
|
||||||
payment_methods: (value) =>
|
payment_methods: (value) =>
|
||||||
value.length === 0 || value.some(
|
value.length === 0 ||
|
||||||
(payment) =>
|
value.some((payment) => payment.name === "cheque" && payment.details === "")
|
||||||
payment.name === "cheque" &&
|
? `${t("a payment method", { capfirst: true })} ${t("is required")}`
|
||||||
payment.details === "") ?
|
: null,
|
||||||
`${t("a payment method", { capfirst: true })} ${t("is required")}` : null,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const roleSelect = useMemo(() => {
|
const roleSelect = useMemo(() => {
|
||||||
return loggedUser?.user?.roles?.map((role) => ({ value: String(role.name), label: role.name }));
|
return loggedUser?.user?.roles?.map((role) => ({
|
||||||
|
value: String(role.name),
|
||||||
|
label: role.name,
|
||||||
|
}));
|
||||||
}, [loggedUser?.user?.roles]);
|
}, [loggedUser?.user?.roles]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal opened={opened} onClose={onClose} title={t("create productor", { capfirst: true })}>
|
<Modal
|
||||||
|
opened={opened}
|
||||||
|
onClose={onClose}
|
||||||
|
title={
|
||||||
|
currentProductor
|
||||||
|
? t("edit productor", { capfirst: true })
|
||||||
|
: t("create productor", { capfirst: true })
|
||||||
|
}
|
||||||
|
>
|
||||||
<Title order={4}>{t("Informations", { capfirst: true })}</Title>
|
<Title order={4}>{t("Informations", { capfirst: true })}</Title>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={t("productor name", { capfirst: true })}
|
label={t("productor name", { capfirst: true })}
|
||||||
@@ -127,7 +137,7 @@ export function ProductorModal({
|
|||||||
<NumberInput
|
<NumberInput
|
||||||
label={t("max cheque number", { capfirst: true })}
|
label={t("max cheque number", { capfirst: true })}
|
||||||
placeholder={t("max cheque number", { capfirst: true })}
|
placeholder={t("max cheque number", { capfirst: true })}
|
||||||
description={t("can be empty default to 3", {capfirst: true})}
|
description={t("can be empty default to 3", { capfirst: true })}
|
||||||
{...form.getInputProps(`payment_methods.${index}.max`)}
|
{...form.getInputProps(`payment_methods.${index}.max`)}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { ActionIcon, Badge, Table, Tooltip } from "@mantine/core";
|
|||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import { IconEdit, IconX } from "@tabler/icons-react";
|
import { IconEdit, IconX } from "@tabler/icons-react";
|
||||||
import type { Productor } from "@/services/resources/productors";
|
import type { Productor } from "@/services/resources/productors";
|
||||||
import { useDeleteProductor } from "@/services/api";
|
|
||||||
import { useNavigate, useSearchParams } from "react-router";
|
import { useNavigate, useSearchParams } from "react-router";
|
||||||
|
|
||||||
export type ProductorRowProps = {
|
export type ProductorRowProps = {
|
||||||
@@ -11,7 +10,6 @@ export type ProductorRowProps = {
|
|||||||
|
|
||||||
export default function ProductorRow({ productor }: ProductorRowProps) {
|
export default function ProductorRow({ productor }: ProductorRowProps) {
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const deleteMutation = useDeleteProductor();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -46,8 +44,11 @@ export default function ProductorRow({ productor }: ProductorRowProps) {
|
|||||||
color="red"
|
color="red"
|
||||||
size="sm"
|
size="sm"
|
||||||
mr="5"
|
mr="5"
|
||||||
onClick={() => {
|
onClick={(e) => {
|
||||||
deleteMutation.mutate(productor.id);
|
e.stopPropagation();
|
||||||
|
navigate(
|
||||||
|
`/dashboard/productors/${productor.id}/delete${searchParams ? `?${searchParams.toString()}` : ""}`,
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconX />
|
<IconX />
|
||||||
|
|||||||
@@ -59,8 +59,7 @@ export function ProductModal({ opened, onClose, currentProduct, handleSubmit }:
|
|||||||
});
|
});
|
||||||
|
|
||||||
const productorsSelect = useMemo(() => {
|
const productorsSelect = useMemo(() => {
|
||||||
if (!productors)
|
if (!productors) return [];
|
||||||
return [];
|
|
||||||
return productors?.map((productor) => ({
|
return productors?.map((productor) => ({
|
||||||
value: String(productor.id),
|
value: String(productor.id),
|
||||||
label: `${productor.name}`,
|
label: `${productor.name}`,
|
||||||
@@ -68,7 +67,15 @@ export function ProductModal({ opened, onClose, currentProduct, handleSubmit }:
|
|||||||
}, [productors]);
|
}, [productors]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal opened={opened} onClose={onClose} title={t("create product", { capfirst: true })}>
|
<Modal
|
||||||
|
opened={opened}
|
||||||
|
onClose={onClose}
|
||||||
|
title={
|
||||||
|
currentProduct
|
||||||
|
? t("edit product", { capfirst: true })
|
||||||
|
: t("create product", { capfirst: true })
|
||||||
|
}
|
||||||
|
>
|
||||||
<Title order={4}>{t("informations", { capfirst: true })}</Title>
|
<Title order={4}>{t("informations", { capfirst: true })}</Title>
|
||||||
<Select
|
<Select
|
||||||
label={t("productor", { capfirst: true })}
|
label={t("productor", { capfirst: true })}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { ActionIcon, Table, Tooltip } from "@mantine/core";
|
|||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import { IconEdit, IconX } from "@tabler/icons-react";
|
import { IconEdit, IconX } from "@tabler/icons-react";
|
||||||
import { ProductType, ProductUnit, type Product } from "@/services/resources/products";
|
import { ProductType, ProductUnit, type Product } from "@/services/resources/products";
|
||||||
import { useDeleteProduct } from "@/services/api";
|
|
||||||
import { useNavigate, useSearchParams } from "react-router";
|
import { useNavigate, useSearchParams } from "react-router";
|
||||||
|
|
||||||
export type ProductRowProps = {
|
export type ProductRowProps = {
|
||||||
@@ -11,7 +10,6 @@ export type ProductRowProps = {
|
|||||||
|
|
||||||
export default function ProductRow({ product }: ProductRowProps) {
|
export default function ProductRow({ product }: ProductRowProps) {
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const deleteMutation = useDeleteProduct();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -59,8 +57,11 @@ export default function ProductRow({ product }: ProductRowProps) {
|
|||||||
color="red"
|
color="red"
|
||||||
size="sm"
|
size="sm"
|
||||||
mr="5"
|
mr="5"
|
||||||
onClick={() => {
|
onClick={(e) => {
|
||||||
deleteMutation.mutate(product.id);
|
e.stopPropagation();
|
||||||
|
navigate(
|
||||||
|
`/dashboard/products/${product.id}/delete${searchParams ? `?${searchParams.toString()}` : ""}`,
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconX />
|
<IconX />
|
||||||
|
|||||||
@@ -48,8 +48,7 @@ export default function ShipmentModal({
|
|||||||
const { data: allProductors } = useGetProductors();
|
const { data: allProductors } = useGetProductors();
|
||||||
|
|
||||||
const formsSelect = useMemo(() => {
|
const formsSelect = useMemo(() => {
|
||||||
if (!allForms)
|
if (!allForms) return [];
|
||||||
return [];
|
|
||||||
return allForms?.map((currentForm) => ({
|
return allForms?.map((currentForm) => ({
|
||||||
value: String(currentForm.id),
|
value: String(currentForm.id),
|
||||||
label: `${currentForm.name} ${currentForm.season}`,
|
label: `${currentForm.name} ${currentForm.season}`,
|
||||||
@@ -75,7 +74,11 @@ export default function ShipmentModal({
|
|||||||
<Modal
|
<Modal
|
||||||
opened={opened}
|
opened={opened}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
title={currentShipment ? t("edit shipment") : t("create shipment")}
|
title={
|
||||||
|
currentShipment
|
||||||
|
? t("edit shipment", { capfirst: true })
|
||||||
|
: t("create shipment", { capfirst: true })
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={t("shipment name", { capfirst: true })}
|
label={t("shipment name", { capfirst: true })}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { ActionIcon, Table, Tooltip } from "@mantine/core";
|
import { ActionIcon, Table, Tooltip } from "@mantine/core";
|
||||||
import { useNavigate, useSearchParams } from "react-router";
|
import { useNavigate, useSearchParams } from "react-router";
|
||||||
import { useDeleteShipment } from "@/services/api";
|
|
||||||
import { IconEdit, IconX } from "@tabler/icons-react";
|
import { IconEdit, IconX } from "@tabler/icons-react";
|
||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import type { Shipment } from "@/services/resources/shipments";
|
import type { Shipment } from "@/services/resources/shipments";
|
||||||
@@ -11,7 +10,6 @@ export type ShipmentRowProps = {
|
|||||||
|
|
||||||
export default function ShipmentRow({ shipment }: ShipmentRowProps) {
|
export default function ShipmentRow({ shipment }: ShipmentRowProps) {
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const deleteMutation = useDeleteShipment();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -20,7 +18,7 @@ export default function ShipmentRow({ shipment }: ShipmentRowProps) {
|
|||||||
<Table.Td>{shipment.date}</Table.Td>
|
<Table.Td>{shipment.date}</Table.Td>
|
||||||
<Table.Td>{`${shipment.form.name} ${shipment.form.season}`}</Table.Td>
|
<Table.Td>{`${shipment.form.name} ${shipment.form.season}`}</Table.Td>
|
||||||
<Table.Td>
|
<Table.Td>
|
||||||
<Tooltip label={t("edit productor", { capfirst: true })}>
|
<Tooltip label={t("edit shipment", { capfirst: true })}>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
size="sm"
|
size="sm"
|
||||||
mr="5"
|
mr="5"
|
||||||
@@ -34,13 +32,16 @@ export default function ShipmentRow({ shipment }: ShipmentRowProps) {
|
|||||||
<IconEdit />
|
<IconEdit />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip label={t("remove productor", { capfirst: true })}>
|
<Tooltip label={t("remove shipment", { capfirst: true })}>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
color="red"
|
color="red"
|
||||||
size="sm"
|
size="sm"
|
||||||
mr="5"
|
mr="5"
|
||||||
onClick={() => {
|
onClick={(e) => {
|
||||||
deleteMutation.mutate(shipment.id);
|
e.stopPropagation();
|
||||||
|
navigate(
|
||||||
|
`/dashboard/shipments/${shipment.id}/delete${searchParams ? `?${searchParams.toString()}` : ""}`,
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconX />
|
<IconX />
|
||||||
|
|||||||
@@ -36,13 +36,20 @@ export function UserModal({ opened, onClose, currentUser, handleSubmit }: UserMo
|
|||||||
});
|
});
|
||||||
|
|
||||||
const roleSelect = useMemo(() => {
|
const roleSelect = useMemo(() => {
|
||||||
if (!allRoles)
|
if (!allRoles) return [];
|
||||||
return [];
|
|
||||||
return allRoles?.map((role) => ({ value: String(role.name), label: role.name }));
|
return allRoles?.map((role) => ({ value: String(role.name), label: role.name }));
|
||||||
}, [allRoles]);
|
}, [allRoles]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal opened={opened} onClose={onClose} title={t("create user", { capfirst: true })}>
|
<Modal
|
||||||
|
opened={opened}
|
||||||
|
onClose={onClose}
|
||||||
|
title={
|
||||||
|
currentUser
|
||||||
|
? t("edit user", { capfirst: true })
|
||||||
|
: t("create user", { capfirst: true })
|
||||||
|
}
|
||||||
|
>
|
||||||
<Title order={4}>{t("informations", { capfirst: true })}</Title>
|
<Title order={4}>{t("informations", { capfirst: true })}</Title>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={t("user name", { capfirst: true })}
|
label={t("user name", { capfirst: true })}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { ActionIcon, Badge, Box, Table, Tooltip } from "@mantine/core";
|
|||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import { IconEdit, IconX } from "@tabler/icons-react";
|
import { IconEdit, IconX } from "@tabler/icons-react";
|
||||||
import { type User } from "@/services/resources/users";
|
import { type User } from "@/services/resources/users";
|
||||||
import { useDeleteUser } from "@/services/api";
|
|
||||||
import { useNavigate, useSearchParams } from "react-router";
|
import { useNavigate, useSearchParams } from "react-router";
|
||||||
|
|
||||||
export type UserRowProps = {
|
export type UserRowProps = {
|
||||||
@@ -11,36 +10,31 @@ export type UserRowProps = {
|
|||||||
|
|
||||||
export default function UserRow({ user }: UserRowProps) {
|
export default function UserRow({ user }: UserRowProps) {
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const deleteMutation = useDeleteUser();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table.Tr key={user.id}>
|
<Table.Tr key={user.id}>
|
||||||
<Table.Td>{user.name}</Table.Td>
|
<Table.Td>{user.name}</Table.Td>
|
||||||
<Table.Td>{user.email}</Table.Td>
|
<Table.Td>{user.email}</Table.Td>
|
||||||
<Table.Td style={{maxWidth: 200}}>
|
<Table.Td style={{ maxWidth: 200 }}>
|
||||||
<Box
|
<Box
|
||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: "flex",
|
||||||
gap: 4
|
gap: 4,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{user.roles.slice(0, 3).map((value) => (
|
{user.roles.slice(0, 3).map((value) => (
|
||||||
<Badge key={value.id} size="xs">
|
<Badge key={value.id} size="xs">
|
||||||
{t(value.name, { capfirst: true })}
|
{t(value.name, { capfirst: true })}
|
||||||
</Badge>
|
</Badge>
|
||||||
))}
|
))}
|
||||||
{
|
{user.roles.length > 3 && (
|
||||||
user.roles.length > 3 && (
|
<Tooltip label={user.roles.slice(3).map((role) => `${role.name} `)}>
|
||||||
<Tooltip
|
|
||||||
label={user.roles.slice(3).map(role=>`${role.name} `)}
|
|
||||||
>
|
|
||||||
<Badge size="xs" variant="light">
|
<Badge size="xs" variant="light">
|
||||||
+{user.roles.length - 3}
|
+{user.roles.length - 3}
|
||||||
</Badge>
|
</Badge>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)
|
)}
|
||||||
}
|
|
||||||
</Box>
|
</Box>
|
||||||
</Table.Td>
|
</Table.Td>
|
||||||
<Table.Td>
|
<Table.Td>
|
||||||
@@ -63,8 +57,11 @@ export default function UserRow({ user }: UserRowProps) {
|
|||||||
color="red"
|
color="red"
|
||||||
size="sm"
|
size="sm"
|
||||||
mr="5"
|
mr="5"
|
||||||
onClick={() => {
|
onClick={(e) => {
|
||||||
deleteMutation.mutate(user.id);
|
e.stopPropagation();
|
||||||
|
navigate(
|
||||||
|
`/dashboard/users/${user.id}/delete${searchParams ? `?${searchParams.toString()}` : ""}`,
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconX />
|
<IconX />
|
||||||
|
|||||||
@@ -51,7 +51,9 @@ export function Contract() {
|
|||||||
payment_method: (value) =>
|
payment_method: (value) =>
|
||||||
!value ? `${t("a payment method", { capfirst: true })} ${t("is required")}` : null,
|
!value ? `${t("a payment method", { capfirst: true })} ${t("is required")}` : null,
|
||||||
cheques: (value, values) =>
|
cheques: (value, values) =>
|
||||||
values.payment_method === "cheque" && value.some((val) => val.name == "") ? `${t("cheque id", {capfirst: true})} ${t("is required")}` : null,
|
values.payment_method === "cheque" && value.some((val) => val.name == "")
|
||||||
|
? `${t("cheque id", { capfirst: true })} ${t("is required")}`
|
||||||
|
: null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -137,12 +139,13 @@ export function Contract() {
|
|||||||
const formValues = inputForm.getValues();
|
const formValues = inputForm.getValues();
|
||||||
const contract = {
|
const contract = {
|
||||||
...formValues,
|
...formValues,
|
||||||
cheque_quantity: formValues.payment_method === "cheque" ? formValues.cheque_quantity : 0,
|
cheque_quantity:
|
||||||
|
formValues.payment_method === "cheque" ? formValues.cheque_quantity : 0,
|
||||||
form_id: form.id,
|
form_id: form.id,
|
||||||
products: tranformProducts(withDefaultValues(formValues.products)),
|
products: tranformProducts(withDefaultValues(formValues.products)),
|
||||||
};
|
};
|
||||||
await createContractMutation.mutateAsync(contract);
|
await createContractMutation.mutateAsync(contract);
|
||||||
window.location.href = '/';
|
window.location.href = "/";
|
||||||
} else {
|
} else {
|
||||||
const firstErrorField = Object.keys(errors.errors)[0];
|
const firstErrorField = Object.keys(errors.errors)[0];
|
||||||
const ref = inputRefs.current[firstErrorField];
|
const ref = inputRefs.current[firstErrorField];
|
||||||
@@ -165,7 +168,7 @@ export function Contract() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack w={{ base: "100%", md: "80%", lg: "50%" }} p={{base: 'xs'}}>
|
<Stack w={{ base: "100%", md: "80%", lg: "50%" }} p={{ base: "xs" }}>
|
||||||
<Title order={2}>{form.name}</Title>
|
<Title order={2}>{form.name}</Title>
|
||||||
<Title order={3}>{t("informations", { capfirst: true })}</Title>
|
<Title order={3}>{t("informations", { capfirst: true })}</Title>
|
||||||
<Text size="sm">
|
<Text size="sm">
|
||||||
@@ -289,11 +292,7 @@ export function Contract() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{inputForm.values.payment_method === "cheque" ? (
|
{inputForm.values.payment_method === "cheque" ? (
|
||||||
<ContractCheque
|
<ContractCheque productor={form?.productor} price={price} inputForm={inputForm} />
|
||||||
productor={form?.productor}
|
|
||||||
price={price}
|
|
||||||
inputForm={inputForm}
|
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
{inputForm.values.payment_method === "transfer" ? (
|
{inputForm.values.payment_method === "transfer" ? (
|
||||||
<Text>
|
<Text>
|
||||||
@@ -321,9 +320,11 @@ export function Contract() {
|
|||||||
}).format(price)}
|
}).format(price)}
|
||||||
</Text>
|
</Text>
|
||||||
<Button
|
<Button
|
||||||
leftSection={<IconDownload/>}
|
leftSection={<IconDownload />}
|
||||||
aria-label={t("submit contracts")} onClick={handleSubmit}>
|
aria-label={t("submit contracts")}
|
||||||
{t("submit", {capfirst: true})}
|
onClick={handleSubmit}
|
||||||
|
>
|
||||||
|
{t("submit", { capfirst: true })}
|
||||||
</Button>
|
</Button>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
import { ActionIcon, Group, Loader, ScrollArea, Stack, Table, Title, Tooltip } from "@mantine/core";
|
import { ActionIcon, Group, Loader, ScrollArea, Stack, Table, Title, Tooltip } from "@mantine/core";
|
||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import { useGetAllContractFile, useGetContracts, useGetRecap } from "@/services/api";
|
import {
|
||||||
|
useDeleteContract,
|
||||||
|
useGetAllContractFile,
|
||||||
|
useGetContract,
|
||||||
|
useGetContracts,
|
||||||
|
useGetRecap,
|
||||||
|
} from "@/services/api";
|
||||||
import { IconDownload, IconTableExport } from "@tabler/icons-react";
|
import { IconDownload, IconTableExport } from "@tabler/icons-react";
|
||||||
import ContractRow from "@/components/Contracts/Row";
|
import ContractRow from "@/components/Contracts/Row";
|
||||||
import { useLocation, useNavigate, useSearchParams } from "react-router";
|
import { useLocation, useNavigate, useSearchParams } from "react-router";
|
||||||
@@ -8,6 +14,7 @@ import { ContractModal } from "@/components/Contracts/Modal";
|
|||||||
import { useCallback, useMemo } from "react";
|
import { useCallback, useMemo } from "react";
|
||||||
import { type Contract } from "@/services/resources/contracts";
|
import { type Contract } from "@/services/resources/contracts";
|
||||||
import ContractsFilters from "@/components/Contracts/Filter";
|
import ContractsFilters from "@/components/Contracts/Filter";
|
||||||
|
import { DeleteModal } from "@/components/DeleteModal";
|
||||||
|
|
||||||
export default function Contracts() {
|
export default function Contracts() {
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
@@ -17,18 +24,29 @@ export default function Contracts() {
|
|||||||
const getRecapMutation = useGetRecap();
|
const getRecapMutation = useGetRecap();
|
||||||
const isdownload = location.pathname.includes("/download");
|
const isdownload = location.pathname.includes("/download");
|
||||||
const isrecap = location.pathname.includes("/export");
|
const isrecap = location.pathname.includes("/export");
|
||||||
|
const isDelete = location.pathname.includes("/delete");
|
||||||
|
|
||||||
|
const deleteId = useMemo(() => {
|
||||||
|
if (isDelete) {
|
||||||
|
return location.pathname.split("/")[3];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, [location]);
|
||||||
|
|
||||||
const closeModal = useCallback(() => {
|
const closeModal = useCallback(() => {
|
||||||
navigate(`/dashboard/contracts${searchParams ? `?${searchParams.toString()}` : ""}`);
|
navigate(`/dashboard/contracts${searchParams ? `?${searchParams.toString()}` : ""}`);
|
||||||
}, [navigate, searchParams]);
|
}, [navigate, searchParams]);
|
||||||
|
|
||||||
const { data: contracts, isPending } = useGetContracts(searchParams);
|
const { data: contracts, isPending } = useGetContracts(searchParams);
|
||||||
|
const { data: currentContract } = useGetContract(Number(deleteId), {
|
||||||
|
enabled: !!deleteId,
|
||||||
|
});
|
||||||
|
|
||||||
const { data: allContracts } = useGetContracts();
|
const { data: allContracts } = useGetContracts();
|
||||||
|
const deleteContractMutation = useDeleteContract();
|
||||||
|
|
||||||
const forms = useMemo(() => {
|
const forms = useMemo(() => {
|
||||||
if (!allContracts)
|
if (!allContracts) return [];
|
||||||
return [];
|
|
||||||
return allContracts
|
return allContracts
|
||||||
?.map((contract: Contract) => contract.form.name)
|
?.map((contract: Contract) => contract.form.name)
|
||||||
.filter((contract, index, array) => array.indexOf(contract) === index);
|
.filter((contract, index, array) => array.indexOf(contract) === index);
|
||||||
@@ -57,11 +75,11 @@ export default function Contracts() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleDownloadRecap = useCallback(
|
const handleDownloadRecap = useCallback(
|
||||||
async (id: number) => {
|
async (id: number) => {
|
||||||
await getRecapMutation.mutateAsync(id);
|
await getRecapMutation.mutateAsync(id);
|
||||||
},
|
},
|
||||||
[getAllContractFilesMutation],
|
[getAllContractFilesMutation],
|
||||||
)
|
);
|
||||||
|
|
||||||
if (!contracts || isPending)
|
if (!contracts || isPending)
|
||||||
return (
|
return (
|
||||||
@@ -87,9 +105,7 @@ export default function Contracts() {
|
|||||||
<IconDownload />
|
<IconDownload />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip
|
<Tooltip label={t("download recap", { capfirst: true })}>
|
||||||
label={t("download recap", { capfirst: true })}
|
|
||||||
>
|
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
disabled={false}
|
disabled={false}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@@ -114,6 +130,18 @@ export default function Contracts() {
|
|||||||
onClose={closeModal}
|
onClose={closeModal}
|
||||||
handleSubmit={handleDownloadRecap}
|
handleSubmit={handleDownloadRecap}
|
||||||
/>
|
/>
|
||||||
|
<DeleteModal
|
||||||
|
opened={isDelete}
|
||||||
|
onClose={closeModal}
|
||||||
|
handleSubmit={(id: number) => {
|
||||||
|
deleteContractMutation.mutate(id);
|
||||||
|
}}
|
||||||
|
entityType={"contract"}
|
||||||
|
entity={{
|
||||||
|
name: `${currentContract?.firstname} ${currentContract?.lastname}`,
|
||||||
|
id: currentContract?.id || 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
<ContractsFilters
|
<ContractsFilters
|
||||||
forms={forms || []}
|
forms={forms || []}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { useAuth } from "@/services/auth/AuthProvider";
|
|||||||
export default function Dashboard() {
|
export default function Dashboard() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const {loggedUser} = useAuth();
|
const { loggedUser } = useAuth();
|
||||||
return (
|
return (
|
||||||
<Tabs
|
<Tabs
|
||||||
w={{ base: "100%", md: "80%", lg: "60%" }}
|
w={{ base: "100%", md: "80%", lg: "60%" }}
|
||||||
@@ -16,17 +16,50 @@ export default function Dashboard() {
|
|||||||
onChange={(value) => navigate(`/dashboard/${value}`)}
|
onChange={(value) => navigate(`/dashboard/${value}`)}
|
||||||
>
|
>
|
||||||
<Tabs.List mb="md">
|
<Tabs.List mb="md">
|
||||||
<Tabs.Tab renderRoot={(props) => (<Link to="/dashboard/help" {...props}></Link>)} value="help">{t("help", { capfirst: true })}</Tabs.Tab>
|
<Tabs.Tab
|
||||||
<Tabs.Tab renderRoot={(props) => (<Link to="/dashboard/productors" {...props}></Link>)} value="productors">{t("productors", { capfirst: true })}</Tabs.Tab>
|
renderRoot={(props) => <Link to="/dashboard/help" {...props}></Link>}
|
||||||
<Tabs.Tab renderRoot={(props) => (<Link to="/dashboard/products" {...props}></Link>)} value="products">{t("products", { capfirst: true })}</Tabs.Tab>
|
value="help"
|
||||||
<Tabs.Tab renderRoot={(props) => (<Link to="/dashboard/forms" {...props}></Link>)} value="forms">{t("forms", { capfirst: true })}</Tabs.Tab>
|
>
|
||||||
<Tabs.Tab renderRoot={(props) => (<Link to="/dashboard/shipments" {...props}></Link>)} value="shipments">{t("shipments", { capfirst: true })}</Tabs.Tab>
|
{t("help", { capfirst: true })}
|
||||||
<Tabs.Tab renderRoot={(props) => (<Link to="/dashboard/contracts" {...props}></Link>)} value="contracts">{t("contracts", { capfirst: true })}</Tabs.Tab>
|
</Tabs.Tab>
|
||||||
{
|
<Tabs.Tab
|
||||||
loggedUser?.user?.roles && loggedUser?.user?.roles?.length > 5 ?
|
renderRoot={(props) => <Link to="/dashboard/productors" {...props}></Link>}
|
||||||
<Tabs.Tab renderRoot={(props) => (<Link to="/dashboard/users" {...props}></Link>)} value="users">{t("users", { capfirst: true })}</Tabs.Tab> :
|
value="productors"
|
||||||
null
|
>
|
||||||
}
|
{t("productors", { capfirst: true })}
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab
|
||||||
|
renderRoot={(props) => <Link to="/dashboard/products" {...props}></Link>}
|
||||||
|
value="products"
|
||||||
|
>
|
||||||
|
{t("products", { capfirst: true })}
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab
|
||||||
|
renderRoot={(props) => <Link to="/dashboard/forms" {...props}></Link>}
|
||||||
|
value="forms"
|
||||||
|
>
|
||||||
|
{t("forms", { capfirst: true })}
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab
|
||||||
|
renderRoot={(props) => <Link to="/dashboard/shipments" {...props}></Link>}
|
||||||
|
value="shipments"
|
||||||
|
>
|
||||||
|
{t("shipments", { capfirst: true })}
|
||||||
|
</Tabs.Tab>
|
||||||
|
<Tabs.Tab
|
||||||
|
renderRoot={(props) => <Link to="/dashboard/contracts" {...props}></Link>}
|
||||||
|
value="contracts"
|
||||||
|
>
|
||||||
|
{t("contracts", { capfirst: true })}
|
||||||
|
</Tabs.Tab>
|
||||||
|
{loggedUser?.user?.roles && loggedUser?.user?.roles?.length > 5 ? (
|
||||||
|
<Tabs.Tab
|
||||||
|
renderRoot={(props) => <Link to="/dashboard/users" {...props}></Link>}
|
||||||
|
value="users"
|
||||||
|
>
|
||||||
|
{t("users", { capfirst: true })}
|
||||||
|
</Tabs.Tab>
|
||||||
|
) : null}
|
||||||
</Tabs.List>
|
</Tabs.List>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import { Stack, Loader, Title, Group, ActionIcon, Tooltip, Table, ScrollArea } from "@mantine/core";
|
import { Stack, Loader, Title, Group, ActionIcon, Tooltip, Table, ScrollArea } from "@mantine/core";
|
||||||
import { useCreateForm, useDeleteForm, useEditForm, useGetForm, useGetReferentForms } from "@/services/api";
|
import {
|
||||||
|
useCreateForm,
|
||||||
|
useDeleteForm,
|
||||||
|
useEditForm,
|
||||||
|
useGetForm,
|
||||||
|
useGetReferentForms,
|
||||||
|
} from "@/services/api";
|
||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import { useLocation, useNavigate, useSearchParams } from "react-router";
|
import { useLocation, useNavigate, useSearchParams } from "react-router";
|
||||||
import { IconPlus } from "@tabler/icons-react";
|
import { IconPlus } from "@tabler/icons-react";
|
||||||
|
|||||||
@@ -242,10 +242,13 @@ export function Help() {
|
|||||||
</Text>
|
</Text>
|
||||||
</Blockquote>
|
</Blockquote>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Title order={3}>{t("export contracts", {capfirst: true})}</Title>
|
<Title order={3}>{t("export contracts", { capfirst: true })}</Title>
|
||||||
<Stack>
|
<Stack>
|
||||||
<Text>
|
<Text>
|
||||||
{t("to export contracts submissions before sending to the productor go to the contracts section", {capfirst: true})}
|
{t(
|
||||||
|
"to export contracts submissions before sending to the productor go to the contracts section",
|
||||||
|
{ capfirst: true },
|
||||||
|
)}
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
ml="4"
|
ml="4"
|
||||||
size="xs"
|
size="xs"
|
||||||
@@ -260,21 +263,32 @@ export function Help() {
|
|||||||
<IconLink />
|
<IconLink />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
</Text>
|
</Text>
|
||||||
<Text>{t("in this page you can view all contracts submissions, you can remove duplicates submission or download a specific contract", {capfirst: true})}</Text>
|
|
||||||
<Text>
|
<Text>
|
||||||
{t("you can download all contracts for your form using the export all", {capfirst: true})}{" "}
|
{t(
|
||||||
<ActionIcon size="sm">
|
"in this page you can view all contracts submissions, you can remove duplicates submission or download a specific contract",
|
||||||
<IconDownload/>
|
{ capfirst: true },
|
||||||
</ActionIcon>{" "}
|
)}
|
||||||
{t("button in top right of the page", { section: t("contracts") })}{" "}
|
|
||||||
{t("in the same corner you can download a recap by clicking on the button", {capfirst: true})}{" "}
|
|
||||||
<ActionIcon size="sm">
|
|
||||||
<IconTableExport/>
|
|
||||||
</ActionIcon>{" "}
|
|
||||||
|
|
||||||
</Text>
|
</Text>
|
||||||
<Text>
|
<Text>
|
||||||
{t("once all contracts downloaded, you can delete the form (to avoid new submissions) and hide it from the home page", {capfirst: true})}
|
{t("you can download all contracts for your form using the export all", {
|
||||||
|
capfirst: true,
|
||||||
|
})}{" "}
|
||||||
|
<ActionIcon size="sm">
|
||||||
|
<IconDownload />
|
||||||
|
</ActionIcon>{" "}
|
||||||
|
{t("button in top right of the page", { section: t("contracts") })}{" "}
|
||||||
|
{t("in the same corner you can download a recap by clicking on the button", {
|
||||||
|
capfirst: true,
|
||||||
|
})}{" "}
|
||||||
|
<ActionIcon size="sm">
|
||||||
|
<IconTableExport />
|
||||||
|
</ActionIcon>{" "}
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
{t(
|
||||||
|
"once all contracts downloaded, you can delete the form (to avoid new submissions) and hide it from the home page",
|
||||||
|
{ capfirst: true },
|
||||||
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Title order={3}>{t("glossary", { capfirst: true })}</Title>
|
<Title order={3}>{t("glossary", { capfirst: true })}</Title>
|
||||||
|
|||||||
@@ -14,21 +14,23 @@ export function Home() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (searchParams.get("sessionExpired")) {
|
if (searchParams.get("sessionExpired")) {
|
||||||
showNotification({
|
showNotification({
|
||||||
title: t("session expired", {capfirst: true}),
|
title: t("session expired", { capfirst: true }),
|
||||||
message: t("your session has expired please log in again", {capfirst: true}),
|
message: t("your session has expired please log in again", { capfirst: true }),
|
||||||
color: "red",
|
color: "red",
|
||||||
autoClose: 5000,
|
autoClose: 5000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (searchParams.get("userNotAllowed")) {
|
if (searchParams.get("userNotAllowed")) {
|
||||||
showNotification({
|
showNotification({
|
||||||
title: t("user not allowed", {capfirst: true}),
|
title: t("user not allowed", { capfirst: true }),
|
||||||
message: t("your keycloak user has no roles, please contact your administrator", {capfirst: true}),
|
message: t("your keycloak user has no roles, please contact your administrator", {
|
||||||
|
capfirst: true,
|
||||||
|
}),
|
||||||
color: "red",
|
color: "red",
|
||||||
autoClose: 5000,
|
autoClose: 5000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [searchParams])
|
}, [searchParams]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack mt="lg">
|
<Stack mt="lg">
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ActionIcon, Group, Loader, ScrollArea, Stack, Table, Title, Tooltip } f
|
|||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import {
|
import {
|
||||||
useCreateProductor,
|
useCreateProductor,
|
||||||
|
useDeleteProductor,
|
||||||
useEditProductor,
|
useEditProductor,
|
||||||
useGetProductor,
|
useGetProductor,
|
||||||
useGetProductors,
|
useGetProductors,
|
||||||
@@ -13,6 +14,7 @@ import { ProductorModal } from "@/components/Productors/Modal";
|
|||||||
import { useCallback, useMemo } from "react";
|
import { useCallback, useMemo } from "react";
|
||||||
import type { Productor, ProductorInputs } from "@/services/resources/productors";
|
import type { Productor, ProductorInputs } from "@/services/resources/productors";
|
||||||
import ProductorsFilters from "@/components/Productors/Filter";
|
import ProductorsFilters from "@/components/Productors/Filter";
|
||||||
|
import { DeleteModal } from "@/components/DeleteModal";
|
||||||
|
|
||||||
export default function Productors() {
|
export default function Productors() {
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
@@ -23,9 +25,10 @@ export default function Productors() {
|
|||||||
const { data: allProductors } = useGetProductors();
|
const { data: allProductors } = useGetProductors();
|
||||||
const isCreate = location.pathname === "/dashboard/productors/create";
|
const isCreate = location.pathname === "/dashboard/productors/create";
|
||||||
const isEdit = location.pathname.includes("/edit");
|
const isEdit = location.pathname.includes("/edit");
|
||||||
|
const isDelete = location.pathname.includes("/delete");
|
||||||
|
|
||||||
const editId = useMemo(() => {
|
const editId = useMemo(() => {
|
||||||
if (isEdit) {
|
if (isEdit || isDelete) {
|
||||||
return location.pathname.split("/")[3];
|
return location.pathname.split("/")[3];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -40,16 +43,14 @@ export default function Productors() {
|
|||||||
}, [navigate, searchParams]);
|
}, [navigate, searchParams]);
|
||||||
|
|
||||||
const names = useMemo(() => {
|
const names = useMemo(() => {
|
||||||
if (!allProductors)
|
if (!allProductors) return [];
|
||||||
return [];
|
|
||||||
return allProductors
|
return allProductors
|
||||||
?.map((productor: Productor) => productor.name)
|
?.map((productor: Productor) => productor.name)
|
||||||
.filter((season, index, array) => array.indexOf(season) === index);
|
.filter((season, index, array) => array.indexOf(season) === index);
|
||||||
}, [allProductors]);
|
}, [allProductors]);
|
||||||
|
|
||||||
const types = useMemo(() => {
|
const types = useMemo(() => {
|
||||||
if (!allProductors)
|
if (!allProductors) return [];
|
||||||
return [];
|
|
||||||
return allProductors
|
return allProductors
|
||||||
?.map((productor: Productor) => productor.type)
|
?.map((productor: Productor) => productor.type)
|
||||||
.filter((productor, index, array) => array.indexOf(productor) === index);
|
.filter((productor, index, array) => array.indexOf(productor) === index);
|
||||||
@@ -57,16 +58,17 @@ export default function Productors() {
|
|||||||
|
|
||||||
const createProductorMutation = useCreateProductor();
|
const createProductorMutation = useCreateProductor();
|
||||||
const editProductorMutation = useEditProductor();
|
const editProductorMutation = useEditProductor();
|
||||||
|
const deleteProductorMutation = useDeleteProductor();
|
||||||
|
|
||||||
const handleCreateProductor = useCallback(
|
const handleCreateProductor = useCallback(
|
||||||
async (productor: ProductorInputs) => {
|
async (productor: ProductorInputs) => {
|
||||||
await createProductorMutation.mutateAsync({
|
await createProductorMutation.mutateAsync({
|
||||||
...productor,
|
...productor,
|
||||||
payment_methods: productor.payment_methods.map((payment) =>( {
|
payment_methods: productor.payment_methods.map((payment) => ({
|
||||||
name: payment.name,
|
name: payment.name,
|
||||||
details: payment.details,
|
details: payment.details,
|
||||||
max: payment.max === "" ? null : payment.max
|
max: payment.max === "" ? null : payment.max,
|
||||||
}))
|
})),
|
||||||
});
|
});
|
||||||
closeModal();
|
closeModal();
|
||||||
},
|
},
|
||||||
@@ -80,11 +82,11 @@ export default function Productors() {
|
|||||||
id: id,
|
id: id,
|
||||||
productor: {
|
productor: {
|
||||||
...productor,
|
...productor,
|
||||||
payment_methods: productor.payment_methods.map((payment) =>( {
|
payment_methods: productor.payment_methods.map((payment) => ({
|
||||||
name: payment.name,
|
name: payment.name,
|
||||||
details: payment.details,
|
details: payment.details,
|
||||||
max: payment.max === "" ? null : payment.max
|
max: payment.max === "" ? null : payment.max,
|
||||||
}))
|
})),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
closeModal();
|
closeModal();
|
||||||
@@ -143,6 +145,15 @@ export default function Productors() {
|
|||||||
currentProductor={currentProductor}
|
currentProductor={currentProductor}
|
||||||
handleSubmit={handleEditProductor}
|
handleSubmit={handleEditProductor}
|
||||||
/>
|
/>
|
||||||
|
<DeleteModal
|
||||||
|
opened={isDelete}
|
||||||
|
onClose={closeModal}
|
||||||
|
handleSubmit={(id: number) => {
|
||||||
|
deleteProductorMutation.mutate(id);
|
||||||
|
}}
|
||||||
|
entityType={"productor"}
|
||||||
|
entity={currentProductor}
|
||||||
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
<ProductorsFilters
|
<ProductorsFilters
|
||||||
names={names || []}
|
names={names || []}
|
||||||
|
|||||||
@@ -1,6 +1,12 @@
|
|||||||
import { ActionIcon, Group, Loader, ScrollArea, Stack, Table, Title, Tooltip } from "@mantine/core";
|
import { ActionIcon, Group, Loader, ScrollArea, Stack, Table, Title, Tooltip } from "@mantine/core";
|
||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import { useCreateProduct, useEditProduct, useGetProduct, useGetProducts } from "@/services/api";
|
import {
|
||||||
|
useCreateProduct,
|
||||||
|
useDeleteProduct,
|
||||||
|
useEditProduct,
|
||||||
|
useGetProduct,
|
||||||
|
useGetProducts,
|
||||||
|
} from "@/services/api";
|
||||||
import { IconPlus } from "@tabler/icons-react";
|
import { IconPlus } from "@tabler/icons-react";
|
||||||
import ProductRow from "@/components/Products/Row";
|
import ProductRow from "@/components/Products/Row";
|
||||||
import { useLocation, useNavigate, useSearchParams } from "react-router";
|
import { useLocation, useNavigate, useSearchParams } from "react-router";
|
||||||
@@ -12,6 +18,7 @@ import {
|
|||||||
type ProductInputs,
|
type ProductInputs,
|
||||||
} from "@/services/resources/products";
|
} from "@/services/resources/products";
|
||||||
import ProductsFilters from "@/components/Products/Filter";
|
import ProductsFilters from "@/components/Products/Filter";
|
||||||
|
import { DeleteModal } from "@/components/DeleteModal";
|
||||||
|
|
||||||
export default function Products() {
|
export default function Products() {
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
@@ -19,9 +26,10 @@ export default function Products() {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const isCreate = location.pathname === "/dashboard/products/create";
|
const isCreate = location.pathname === "/dashboard/products/create";
|
||||||
const isEdit = location.pathname.includes("/edit");
|
const isEdit = location.pathname.includes("/edit");
|
||||||
|
const isDelete = location.pathname.includes("/delete");
|
||||||
|
|
||||||
const editId = useMemo(() => {
|
const editId = useMemo(() => {
|
||||||
if (isEdit) {
|
if (isEdit || isDelete) {
|
||||||
return location.pathname.split("/")[3];
|
return location.pathname.split("/")[3];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -38,16 +46,14 @@ export default function Products() {
|
|||||||
const { data: allProducts } = useGetProducts();
|
const { data: allProducts } = useGetProducts();
|
||||||
|
|
||||||
const names = useMemo(() => {
|
const names = useMemo(() => {
|
||||||
if (!allProducts)
|
if (!allProducts) return [];
|
||||||
return [];
|
|
||||||
return allProducts
|
return allProducts
|
||||||
?.map((product: Product) => product.name)
|
?.map((product: Product) => product.name)
|
||||||
.filter((season, index, array) => array.indexOf(season) === index);
|
.filter((season, index, array) => array.indexOf(season) === index);
|
||||||
}, [allProducts]);
|
}, [allProducts]);
|
||||||
|
|
||||||
const productors = useMemo(() => {
|
const productors = useMemo(() => {
|
||||||
if (!allProducts)
|
if (!allProducts) return [];
|
||||||
return [];
|
|
||||||
return allProducts
|
return allProducts
|
||||||
?.map((product: Product) => product.productor.name)
|
?.map((product: Product) => product.productor.name)
|
||||||
.filter((productor, index, array) => array.indexOf(productor) === index);
|
.filter((productor, index, array) => array.indexOf(productor) === index);
|
||||||
@@ -55,6 +61,7 @@ export default function Products() {
|
|||||||
|
|
||||||
const createProductMutation = useCreateProduct();
|
const createProductMutation = useCreateProduct();
|
||||||
const editProductMutation = useEditProduct();
|
const editProductMutation = useEditProduct();
|
||||||
|
const deleteProductMutation = useDeleteProduct();
|
||||||
|
|
||||||
const handleCreateProduct = useCallback(
|
const handleCreateProduct = useCallback(
|
||||||
async (product: ProductInputs) => {
|
async (product: ProductInputs) => {
|
||||||
@@ -134,6 +141,15 @@ export default function Products() {
|
|||||||
currentProduct={currentProduct}
|
currentProduct={currentProduct}
|
||||||
handleSubmit={handleEditProduct}
|
handleSubmit={handleEditProduct}
|
||||||
/>
|
/>
|
||||||
|
<DeleteModal
|
||||||
|
opened={isDelete}
|
||||||
|
onClose={closeModal}
|
||||||
|
handleSubmit={(id: number) => {
|
||||||
|
deleteProductMutation.mutate(id);
|
||||||
|
}}
|
||||||
|
entityType={"product"}
|
||||||
|
entity={currentProduct}
|
||||||
|
/>
|
||||||
<ScrollArea type="auto">
|
<ScrollArea type="auto">
|
||||||
<Table striped>
|
<Table striped>
|
||||||
<Table.Thead>
|
<Table.Thead>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ActionIcon, Group, Loader, ScrollArea, Stack, Table, Title, Tooltip } f
|
|||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import {
|
import {
|
||||||
useCreateShipment,
|
useCreateShipment,
|
||||||
|
useDeleteShipment,
|
||||||
useEditShipment,
|
useEditShipment,
|
||||||
useGetShipment,
|
useGetShipment,
|
||||||
useGetShipments,
|
useGetShipments,
|
||||||
@@ -17,6 +18,7 @@ import {
|
|||||||
} from "@/services/resources/shipments";
|
} from "@/services/resources/shipments";
|
||||||
import ShipmentModal from "@/components/Shipments/Modal";
|
import ShipmentModal from "@/components/Shipments/Modal";
|
||||||
import ShipmentsFilters from "@/components/Shipments/Filter";
|
import ShipmentsFilters from "@/components/Shipments/Filter";
|
||||||
|
import { DeleteModal } from "@/components/DeleteModal";
|
||||||
|
|
||||||
export default function Shipments() {
|
export default function Shipments() {
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
@@ -25,9 +27,10 @@ export default function Shipments() {
|
|||||||
|
|
||||||
const isCreate = location.pathname === "/dashboard/shipments/create";
|
const isCreate = location.pathname === "/dashboard/shipments/create";
|
||||||
const isEdit = location.pathname.includes("/edit");
|
const isEdit = location.pathname.includes("/edit");
|
||||||
|
const isDelete = location.pathname.includes("/delete");
|
||||||
|
|
||||||
const editId = useMemo(() => {
|
const editId = useMemo(() => {
|
||||||
if (isEdit) {
|
if (isEdit || isDelete) {
|
||||||
return location.pathname.split("/")[3];
|
return location.pathname.split("/")[3];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -44,16 +47,14 @@ export default function Shipments() {
|
|||||||
const { data: allShipments } = useGetShipments();
|
const { data: allShipments } = useGetShipments();
|
||||||
|
|
||||||
const names = useMemo(() => {
|
const names = useMemo(() => {
|
||||||
if (!allShipments)
|
if (!allShipments) return [];
|
||||||
return [];
|
|
||||||
return allShipments
|
return allShipments
|
||||||
?.map((shipment: Shipment) => shipment.name)
|
?.map((shipment: Shipment) => shipment.name)
|
||||||
.filter((season, index, array) => array.indexOf(season) === index);
|
.filter((season, index, array) => array.indexOf(season) === index);
|
||||||
}, [allShipments]);
|
}, [allShipments]);
|
||||||
|
|
||||||
const forms = useMemo(() => {
|
const forms = useMemo(() => {
|
||||||
if (!allShipments)
|
if (!allShipments) return [];
|
||||||
return [];
|
|
||||||
return allShipments
|
return allShipments
|
||||||
?.map((shipment: Shipment) => shipment.form.name)
|
?.map((shipment: Shipment) => shipment.form.name)
|
||||||
.filter((season, index, array) => array.indexOf(season) === index);
|
.filter((season, index, array) => array.indexOf(season) === index);
|
||||||
@@ -61,6 +62,7 @@ export default function Shipments() {
|
|||||||
|
|
||||||
const createShipmentMutation = useCreateShipment();
|
const createShipmentMutation = useCreateShipment();
|
||||||
const editShipmentMutation = useEditShipment();
|
const editShipmentMutation = useEditShipment();
|
||||||
|
const deleteShipmentMutation = useDeleteShipment();
|
||||||
|
|
||||||
const handleCreateShipment = useCallback(
|
const handleCreateShipment = useCallback(
|
||||||
async (shipment: ShipmentInputs) => {
|
async (shipment: ShipmentInputs) => {
|
||||||
@@ -133,6 +135,15 @@ export default function Shipments() {
|
|||||||
currentShipment={currentShipment}
|
currentShipment={currentShipment}
|
||||||
handleSubmit={handleEditShipment}
|
handleSubmit={handleEditShipment}
|
||||||
/>
|
/>
|
||||||
|
<DeleteModal
|
||||||
|
opened={isDelete}
|
||||||
|
onClose={closeModal}
|
||||||
|
handleSubmit={(id: number) => {
|
||||||
|
deleteShipmentMutation.mutate(id);
|
||||||
|
}}
|
||||||
|
entityType={"shipment"}
|
||||||
|
entity={currentShipment}
|
||||||
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
<ShipmentsFilters
|
<ShipmentsFilters
|
||||||
forms={forms || []}
|
forms={forms || []}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ActionIcon, Group, Loader, ScrollArea, Stack, Table, Title, Tooltip } from "@mantine/core";
|
import { ActionIcon, Group, Loader, ScrollArea, Stack, Table, Title, Tooltip } from "@mantine/core";
|
||||||
import { t } from "@/config/i18n";
|
import { t } from "@/config/i18n";
|
||||||
import { useCreateUser, useEditUser, useGetUser, useGetUsers } from "@/services/api";
|
import { useCreateUser, useDeleteUser, useEditUser, useGetUser, useGetUsers } from "@/services/api";
|
||||||
import { IconPlus } from "@tabler/icons-react";
|
import { IconPlus } from "@tabler/icons-react";
|
||||||
import UserRow from "@/components/Users/Row";
|
import UserRow from "@/components/Users/Row";
|
||||||
import { useLocation, useNavigate, useSearchParams } from "react-router";
|
import { useLocation, useNavigate, useSearchParams } from "react-router";
|
||||||
@@ -8,6 +8,7 @@ import { UserModal } from "@/components/Users/Modal";
|
|||||||
import { useCallback, useMemo } from "react";
|
import { useCallback, useMemo } from "react";
|
||||||
import { type User, type UserInputs } from "@/services/resources/users";
|
import { type User, type UserInputs } from "@/services/resources/users";
|
||||||
import UsersFilters from "@/components/Users/Filter";
|
import UsersFilters from "@/components/Users/Filter";
|
||||||
|
import { DeleteModal } from "@/components/DeleteModal";
|
||||||
|
|
||||||
export default function Users() {
|
export default function Users() {
|
||||||
const [searchParams, setSearchParams] = useSearchParams();
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
@@ -16,9 +17,10 @@ export default function Users() {
|
|||||||
|
|
||||||
const isCreate = location.pathname === "/dashboard/users/create";
|
const isCreate = location.pathname === "/dashboard/users/create";
|
||||||
const isEdit = location.pathname.includes("/edit");
|
const isEdit = location.pathname.includes("/edit");
|
||||||
|
const isDelete = location.pathname.includes("/delete");
|
||||||
|
|
||||||
const editId = useMemo(() => {
|
const editId = useMemo(() => {
|
||||||
if (isEdit) {
|
if (isEdit || isDelete) {
|
||||||
return location.pathname.split("/")[3];
|
return location.pathname.split("/")[3];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@@ -36,8 +38,7 @@ export default function Users() {
|
|||||||
const { data: allUsers } = useGetUsers();
|
const { data: allUsers } = useGetUsers();
|
||||||
|
|
||||||
const names = useMemo(() => {
|
const names = useMemo(() => {
|
||||||
if (!allUsers)
|
if (!allUsers) return [];
|
||||||
return [];
|
|
||||||
return allUsers
|
return allUsers
|
||||||
?.map((user: User) => user.name)
|
?.map((user: User) => user.name)
|
||||||
.filter((season, index, array) => array.indexOf(season) === index);
|
.filter((season, index, array) => array.indexOf(season) === index);
|
||||||
@@ -45,6 +46,7 @@ export default function Users() {
|
|||||||
|
|
||||||
const createUserMutation = useCreateUser();
|
const createUserMutation = useCreateUser();
|
||||||
const editUserMutation = useEditUser();
|
const editUserMutation = useEditUser();
|
||||||
|
const deleteUserMutation = useDeleteUser();
|
||||||
|
|
||||||
const handleCreateUser = useCallback(
|
const handleCreateUser = useCallback(
|
||||||
async (user: UserInputs) => {
|
async (user: UserInputs) => {
|
||||||
@@ -117,6 +119,15 @@ export default function Users() {
|
|||||||
currentUser={currentUser}
|
currentUser={currentUser}
|
||||||
handleSubmit={handleEditUser}
|
handleSubmit={handleEditUser}
|
||||||
/>
|
/>
|
||||||
|
<DeleteModal
|
||||||
|
opened={isDelete}
|
||||||
|
onClose={closeModal}
|
||||||
|
handleSubmit={(id: number) => {
|
||||||
|
deleteUserMutation.mutate(id);
|
||||||
|
}}
|
||||||
|
entityType={"user"}
|
||||||
|
entity={currentUser}
|
||||||
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
<UsersFilters
|
<UsersFilters
|
||||||
names={names || []}
|
names={names || []}
|
||||||
|
|||||||
@@ -34,21 +34,26 @@ export const router = createBrowserRouter([
|
|||||||
{ path: "productors", Component: Productors },
|
{ path: "productors", Component: Productors },
|
||||||
{ path: "productors/create", Component: Productors },
|
{ path: "productors/create", Component: Productors },
|
||||||
{ path: "productors/:id/edit", Component: Productors },
|
{ path: "productors/:id/edit", Component: Productors },
|
||||||
|
{ path: "productors/:id/delete", Component: Productors },
|
||||||
{ path: "products", Component: Products },
|
{ path: "products", Component: Products },
|
||||||
{ path: "products/create", Component: Products },
|
{ path: "products/create", Component: Products },
|
||||||
{ path: "products/:id/edit", Component: Products },
|
{ path: "products/:id/edit", Component: Products },
|
||||||
|
{ path: "products/:id/delete", Component: Products },
|
||||||
{ path: "contracts", Component: Contracts },
|
{ path: "contracts", Component: Contracts },
|
||||||
{ path: "contracts/download", Component: Contracts },
|
{ path: "contracts/download", Component: Contracts },
|
||||||
{ path: "contracts/export", Component: Contracts },
|
{ path: "contracts/export", Component: Contracts },
|
||||||
|
{ path: "contracts/:id/delete", Component: Contracts },
|
||||||
{ path: "users", Component: Users },
|
{ path: "users", Component: Users },
|
||||||
{ path: "users/create", Component: Users },
|
{ path: "users/create", Component: Users },
|
||||||
{ path: "users/:id/edit", Component: Users },
|
{ path: "users/:id/edit", Component: Users },
|
||||||
|
{ path: "users/:id/delete", Component: Users },
|
||||||
{ path: "forms", Component: Forms },
|
{ path: "forms", Component: Forms },
|
||||||
{ path: "forms/:id/edit", Component: Forms },
|
{ path: "forms/:id/edit", Component: Forms },
|
||||||
{ path: "forms/:id/delete", Component: Forms },
|
{ path: "forms/:id/delete", Component: Forms },
|
||||||
{ path: "forms/create", Component: Forms },
|
{ path: "forms/create", Component: Forms },
|
||||||
{ path: "shipments", Component: Shipments },
|
{ path: "shipments", Component: Shipments },
|
||||||
{ path: "shipments/:id/edit", Component: Shipments },
|
{ path: "shipments/:id/edit", Component: Shipments },
|
||||||
|
{ path: "shipments/:id/delete", Component: Shipments },
|
||||||
{ path: "shipments/create", Component: Shipments },
|
{ path: "shipments/create", Component: Shipments },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,23 +5,19 @@ import type { UserLogged } from "../resources/users";
|
|||||||
export type Auth = {
|
export type Auth = {
|
||||||
loggedUser: UserLogged | null;
|
loggedUser: UserLogged | null;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
}
|
};
|
||||||
|
|
||||||
const AuthContext = createContext<Auth | undefined>(undefined)
|
const AuthContext = createContext<Auth | undefined>(undefined);
|
||||||
|
|
||||||
export function AuthProvider({ children }: {children: React.ReactNode}) {
|
export function AuthProvider({ children }: { children: React.ReactNode }) {
|
||||||
const {data: loggedUser, isLoading} = useCurrentUser();
|
const { data: loggedUser, isLoading } = useCurrentUser();
|
||||||
|
|
||||||
const value: Auth = {
|
const value: Auth = {
|
||||||
loggedUser: loggedUser ?? null,
|
loggedUser: loggedUser ?? null,
|
||||||
isLoading,
|
isLoading,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||||
<AuthContext.Provider value={value}>
|
|
||||||
{children}
|
|
||||||
</AuthContext.Provider>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useAuth(): Auth {
|
export function useAuth(): Auth {
|
||||||
|
|||||||
Reference in New Issue
Block a user