add contract storage fix various bugs and translations
This commit is contained in:
@@ -10,6 +10,8 @@ import {
|
||||
List,
|
||||
Loader,
|
||||
Overlay,
|
||||
Select,
|
||||
Space,
|
||||
Stack,
|
||||
Text,
|
||||
TextInput,
|
||||
@@ -20,16 +22,22 @@ import { IconMail, IconPhone, IconUser } from "@tabler/icons-react";
|
||||
import { useCallback, useMemo, useRef } from "react";
|
||||
import { useParams } from "react-router";
|
||||
import { computePrices } from "./price";
|
||||
import { ContractCheque } from "@/components/PaymentMethods/Cheque";
|
||||
import { tranformProducts, type ContractInputs } from "@/services/resources/contracts";
|
||||
|
||||
export function Contract() {
|
||||
const { id } = useParams();
|
||||
const { data: form } = useGetForm(Number(id), { enabled: !!id });
|
||||
const inputForm = useForm<Record<string, number | string>>({
|
||||
const inputForm = useForm<ContractInputs>({
|
||||
initialValues: {
|
||||
firstname: "",
|
||||
lastname: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
payment_method: "",
|
||||
cheque_quantity: 1,
|
||||
cheques: [],
|
||||
products: {},
|
||||
},
|
||||
validate: {
|
||||
firstname: (value) =>
|
||||
@@ -40,6 +48,8 @@ export function Contract() {
|
||||
!value ? `${t("a email", { capfirst: true })} ${t("is required")}` : null,
|
||||
phone: (value) =>
|
||||
!value ? `${t("a phone", { capfirst: true })} ${t("is required")}` : null,
|
||||
payment_method: (value) =>
|
||||
!value ? `${t("a payment method", { capfirst: true })} ${t("is required")}` : null,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -61,8 +71,8 @@ export function Contract() {
|
||||
if (!allProducts) {
|
||||
return 0;
|
||||
}
|
||||
const values = Object.entries(inputForm.getValues());
|
||||
return computePrices(values, allProducts, form?.shipments.length);
|
||||
const productValues = Object.entries(inputForm.getValues().products);
|
||||
return computePrices(productValues, allProducts, form?.shipments.length);
|
||||
}, [inputForm, allProducts, form?.shipments]);
|
||||
|
||||
const inputRefs = useRef<Record<string, HTMLInputElement | null>>({
|
||||
@@ -70,6 +80,7 @@ export function Contract() {
|
||||
lastname: null,
|
||||
email: null,
|
||||
phone: null,
|
||||
payment_method: null,
|
||||
});
|
||||
|
||||
const isShipmentsMinimumValue = useCallback(() => {
|
||||
@@ -77,7 +88,7 @@ export function Contract() {
|
||||
const shipmentErrors = form.shipments
|
||||
.map((shipment) => {
|
||||
const total = computePrices(
|
||||
Object.entries(inputForm.getValues()),
|
||||
Object.entries(inputForm.getValues().products),
|
||||
shipment.products,
|
||||
);
|
||||
if (total < (form?.minimum_shipment_value || 0)) {
|
||||
@@ -122,8 +133,9 @@ export function Contract() {
|
||||
}
|
||||
if (inputForm.isValid() && isShipmentsMinimumValue()) {
|
||||
const contract = {
|
||||
...inputForm.getValues(),
|
||||
form_id: form.id,
|
||||
contract: withDefaultValues(inputForm.getValues()),
|
||||
products: tranformProducts(withDefaultValues(inputForm.getValues().products)),
|
||||
};
|
||||
await createContractMutation.mutateAsync(contract);
|
||||
} else {
|
||||
@@ -253,6 +265,36 @@ export function Contract() {
|
||||
</Accordion>
|
||||
</>
|
||||
) : null}
|
||||
<Title order={3}>{t("payment method", { capfirst: true })}</Title>
|
||||
<Select
|
||||
label={t("payment method", { capfirst: true })}
|
||||
placeholder={t("enter payment method", { capfirst: true })}
|
||||
description={t("choose payment method", { capfirst: true })}
|
||||
data={form.productor.payment_methods.map((payment) => ({
|
||||
value: payment.name,
|
||||
label: t(payment.name, { capfirst: true }),
|
||||
}))}
|
||||
{...inputForm.getInputProps("payment_method")}
|
||||
ref={(el) => {
|
||||
inputRefs.current.payment_method = el;
|
||||
}}
|
||||
/>
|
||||
{inputForm.values.payment_method === "cheque" ? (
|
||||
<ContractCheque
|
||||
chequeOrder={
|
||||
form?.productor?.payment_methods.find((el) => el.name === "cheque")
|
||||
?.details || ""
|
||||
}
|
||||
price={price}
|
||||
inputForm={inputForm}
|
||||
/>
|
||||
) : null}
|
||||
{inputForm.values.payment_method === "transfer" ? (
|
||||
<Text>
|
||||
{t("for transfer method contact your referer or productor", { capfirst: true })}
|
||||
</Text>
|
||||
) : null}
|
||||
<Space h="15vh"></Space>
|
||||
<Overlay
|
||||
bg={"lightGray"}
|
||||
h="10vh"
|
||||
|
||||
120
frontend/src/pages/Contracts/index.tsx
Normal file
120
frontend/src/pages/Contracts/index.tsx
Normal file
@@ -0,0 +1,120 @@
|
||||
import { ActionIcon, Group, Loader, ScrollArea, Stack, Table, Title, Tooltip } from "@mantine/core";
|
||||
import { t } from "@/config/i18n";
|
||||
import { useCreateContract, useGetContract, useGetContracts } from "@/services/api";
|
||||
import { IconPlus } from "@tabler/icons-react";
|
||||
import ContractRow from "@/components/Contracts/Row";
|
||||
import { useLocation, useNavigate, useSearchParams } from "react-router";
|
||||
import { ContractModal } from "@/components/Contracts/Modal";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { type Contract, type ContractInputs } from "@/services/resources/contracts";
|
||||
import ContractsFilters from "@/components/Contracts/Filter";
|
||||
|
||||
export default function Contracts() {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
// const location = useLocation();
|
||||
// const navigate = useNavigate();
|
||||
|
||||
// const isCreate = location.pathname === "/dashboard/contracts/create";
|
||||
// const isEdit = location.pathname.includes("/edit");
|
||||
|
||||
// const editId = useMemo(() => {
|
||||
// if (isEdit) {
|
||||
// return location.pathname.split("/")[3];
|
||||
// }
|
||||
// return null;
|
||||
// }, [location, isEdit]);
|
||||
|
||||
// const closeModal = useCallback(() => {
|
||||
// navigate(`/dashboard/contracts${searchParams ? `?${searchParams.toString()}` : ""}`);
|
||||
// }, [navigate, searchParams]);
|
||||
|
||||
const { data: contracts, isPending } = useGetContracts(searchParams);
|
||||
// const { data: currentContract } = useGetContract(Number(editId), {
|
||||
// enabled: !!editId,
|
||||
// });
|
||||
|
||||
const { data: allContracts } = useGetContracts();
|
||||
|
||||
const forms = useMemo(() => {
|
||||
return allContracts
|
||||
?.map((contract: Contract) => contract.form.name)
|
||||
.filter((contract, index, array) => array.indexOf(contract) === index);
|
||||
}, [allContracts]);
|
||||
|
||||
const onFilterChange = useCallback(
|
||||
(values: string[], filter: string) => {
|
||||
setSearchParams((prev) => {
|
||||
const params = new URLSearchParams(prev);
|
||||
params.delete(filter);
|
||||
|
||||
values.forEach((value) => {
|
||||
params.append(filter, value);
|
||||
});
|
||||
return params;
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
);
|
||||
|
||||
if (!contracts || isPending)
|
||||
return (
|
||||
<Group align="center" justify="center" h="80vh" w="100%">
|
||||
<Loader color="pink" />
|
||||
</Group>
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Group justify="space-between">
|
||||
<Title order={2}>{t("all referers", { capfirst: true })}</Title>
|
||||
{/* <Tooltip label={t("create contract", { capfirst: true })}>
|
||||
<ActionIcon
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
navigate(
|
||||
`/dashboard/contracts/create${searchParams ? `?${searchParams.toString()}` : ""}`,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<IconPlus />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<ContractModal
|
||||
key={`${currentContract?.id}_create`}
|
||||
opened={isCreate}
|
||||
onClose={closeModal}
|
||||
handleSubmit={handleCreateContract}
|
||||
/>
|
||||
<ContractModal
|
||||
key={`${currentContract?.id}_edit`}
|
||||
opened={isEdit}
|
||||
onClose={closeModal}
|
||||
currentContract={currentContract}
|
||||
handleSubmit={handleEditContract}
|
||||
/> */}
|
||||
</Group>
|
||||
<ContractsFilters
|
||||
forms={forms || []}
|
||||
filters={searchParams}
|
||||
onFilterChange={onFilterChange}
|
||||
/>
|
||||
<ScrollArea type="auto">
|
||||
<Table striped>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>{t("name", { capfirst: true })}</Table.Th>
|
||||
<Table.Th>{t("email", { capfirst: true })}</Table.Th>
|
||||
<Table.Th>{t("payment method", { capfirst: true })}</Table.Th>
|
||||
<Table.Th>{t("actions", { capfirst: true })}</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.Tbody>
|
||||
{contracts.map((contract) => (
|
||||
<ContractRow contract={contract} key={contract.id} />
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -19,7 +19,7 @@ export default function Dashboard() {
|
||||
<Tabs.Tab value="products">{t("products", { capfirst: true })}</Tabs.Tab>
|
||||
<Tabs.Tab value="forms">{t("forms", { capfirst: true })}</Tabs.Tab>
|
||||
<Tabs.Tab value="shipments">{t("shipments", { capfirst: true })}</Tabs.Tab>
|
||||
{/* <Tabs.Tab value="templates">{t("templates", {capfirst: true})}</Tabs.Tab> */}
|
||||
<Tabs.Tab value="contracts">{t("contracts", { capfirst: true })}</Tabs.Tab>
|
||||
<Tabs.Tab value="users">{t("users", { capfirst: true })}</Tabs.Tab>
|
||||
</Tabs.List>
|
||||
<Outlet />
|
||||
|
||||
@@ -89,7 +89,7 @@ export default function Users() {
|
||||
return (
|
||||
<Stack>
|
||||
<Group justify="space-between">
|
||||
<Title order={2}>{t("all users", { capfirst: true })}</Title>
|
||||
<Title order={2}>{t("all referers", { capfirst: true })}</Title>
|
||||
<Tooltip label={t("create user", { capfirst: true })}>
|
||||
<ActionIcon
|
||||
onClick={(e) => {
|
||||
|
||||
Reference in New Issue
Block a user