update request

This commit is contained in:
hamid zarghami
2026-06-07 14:27:48 +03:30
parent 17717eb195
commit 2804cc4100
4 changed files with 53 additions and 121 deletions
+4 -10
View File
@@ -9,6 +9,7 @@ export const Paths = {
}, },
designer: { designer: {
request: "/designer/request", request: "/designer/request",
list: "/designer/requests/list",
}, },
}; };
@@ -19,20 +20,13 @@ const businessCatalogPathPrefix = Paths.catalog.business;
/** Public business catalogue grid: /business/:slug */ /** Public business catalogue grid: /business/:slug */
export const isBusinessCatalogPath = (pathname: string): boolean => { export const isBusinessCatalogPath = (pathname: string): boolean => {
return ( return pathname.startsWith(businessCatalogPathPrefix) && pathname.length > businessCatalogPathPrefix.length;
pathname.startsWith(businessCatalogPathPrefix) &&
pathname.length > businessCatalogPathPrefix.length
);
}; };
/** Full-screen viewer: /viewer/:id or /catalogue/:slug (not the list at /catalogue). */ /** Full-screen viewer: /viewer/:id or /catalogue/:slug (not the list at /catalogue). */
export const isViewerPath = (pathname: string): boolean => { export const isViewerPath = (pathname: string): boolean => {
const isViewerById = const isViewerById = pathname.startsWith(viewerPathPrefix) && pathname.length > viewerPathPrefix.length;
pathname.startsWith(viewerPathPrefix) && const isViewerBySlug = pathname.startsWith(viewerBySlugPathPrefix) && pathname.length > viewerBySlugPathPrefix.length;
pathname.length > viewerPathPrefix.length;
const isViewerBySlug =
pathname.startsWith(viewerBySlugPathPrefix) &&
pathname.length > viewerBySlugPathPrefix.length;
return isViewerById || isViewerBySlug; return isViewerById || isViewerBySlug;
}; };
+1 -3
View File
@@ -1,17 +1,15 @@
import DesignerRequestForm from "@/pages/designer/components/DesignerRequestForm"; import DesignerRequestForm from "@/pages/designer/components/DesignerRequestForm";
import { useSubmitDesignRequest } from "@/pages/designer/hooks/useDesignerData";
import { usePageTitle } from "@/hooks/usePageTitle"; import { usePageTitle } from "@/hooks/usePageTitle";
import { type FC } from "react"; import { type FC } from "react";
const DesignerRequest: FC = () => { const DesignerRequest: FC = () => {
usePageTitle("درخواست طراحی"); usePageTitle("درخواست طراحی");
const handleSubmit = useSubmitDesignRequest();
return ( return (
<div className="mt-4 w-full"> <div className="mt-4 w-full">
<h1>درخواست طراحی کاتالوگ</h1> <h1>درخواست طراحی کاتالوگ</h1>
<div className="mt-6 rounded-[32px] bg-white p-4 md:p-6 lg:p-8"> <div className="mt-6 rounded-[32px] bg-white p-4 md:p-6 lg:p-8">
<DesignerRequestForm onSubmit={handleSubmit} /> <DesignerRequestForm />
</div> </div>
</div> </div>
); );
@@ -3,35 +3,20 @@ import DatePicker from "@/components/DatePicker";
import Error from "@/components/Error"; import Error from "@/components/Error";
import Input from "@/components/Input"; import Input from "@/components/Input";
import Textarea from "@/components/Textarea"; import Textarea from "@/components/Textarea";
import { toast } from "@/components/Toast";
import UploadBoxDraggble from "@/components/UploadBoxDraggble"; import UploadBoxDraggble from "@/components/UploadBoxDraggble";
import { import { Paths } from "@/config/Paths";
designerRequestInitialValues, import { extractErrorMessage } from "@/helpers/utils";
designerRequestValidationSchema, import { designerRequestInitialValues, designerRequestValidationSchema, getTotalPrice, PRICE_PER_PAGE, toDesignRequestParams } from "@/pages/designer/designerRequestForm";
getTotalPrice, import { useInitiateDesignRequest } from "@/pages/designer/hooks/useDesignerData";
PRICE_PER_PAGE,
} from "@/pages/designer/designerRequestForm";
import type { DesignerRequestFormValues } from "@/pages/designer/types/Types"; import type { DesignerRequestFormValues } from "@/pages/designer/types/Types";
import { useMultipleUpload } from "@/pages/uploader/hooks/useUploaderData";
import { Form, Formik, useFormikContext, type FormikHelpers } from "formik"; import { Form, Formik, useFormikContext, type FormikHelpers } from "formik";
import { type FC } from "react"; import { type FC } from "react";
import { useNavigate } from "react-router-dom";
type Props = {
onSubmit: (
values: DesignerRequestFormValues,
helpers: FormikHelpers<DesignerRequestFormValues>,
) => void | Promise<void>;
};
const DesignerRequestFormFields: FC = () => { const DesignerRequestFormFields: FC = () => {
const { const { values, errors, touched, isSubmitting, setFieldValue, setFieldTouched, handleChange, handleBlur } = useFormikContext<DesignerRequestFormValues>();
values,
errors,
touched,
isSubmitting,
setFieldValue,
setFieldTouched,
handleChange,
handleBlur,
} = useFormikContext<DesignerRequestFormValues>();
const totalPrice = getTotalPrice(values.count); const totalPrice = getTotalPrice(values.count);
@@ -42,14 +27,7 @@ const DesignerRequestFormFields: FC = () => {
return ( return (
<Form className="mt-6 space-y-5"> <Form className="mt-6 space-y-5">
<Input <Input label="عنوان کاتالوگ" name="title" value={values.title} onChange={handleChange} onBlur={handleBlur} error_text={touched.title ? errors.title : undefined} />
label="عنوان کاتالوگ"
name="title"
value={values.title}
onChange={handleChange}
onBlur={handleBlur}
error_text={touched.title ? errors.title : undefined}
/>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2"> <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
<DatePicker <DatePicker
@@ -77,46 +55,21 @@ const DesignerRequestFormFields: FC = () => {
/> />
</div> </div>
<Textarea <Textarea label="توضیحات" name="desc" value={values.desc} onChange={handleChange} onBlur={handleBlur} className="min-h-[96px]" error_text={touched.desc ? errors.desc : undefined} />
label="توضیحات"
name="desc"
value={values.desc}
onChange={handleChange}
onBlur={handleBlur}
className="min-h-[96px]"
error_text={touched.desc ? errors.desc : undefined}
/>
<div> <div>
<div className="mb-2 text-sm">فایل های ضمیمه</div> <div className="mb-2 text-sm">فایل های ضمیمه</div>
<UploadBoxDraggble <UploadBoxDraggble label="فایل مورد نظر را آپلود کنید" onChange={handleAttachmentChange} isMultiple isFile isLoading={isSubmitting} loadingLabel="در حال ثبت درخواست..." />
label="فایل مورد نظر را آپلود کنید" {touched.attachments && errors.attachments ? <Error errorText={String(errors.attachments)} /> : null}
onChange={handleAttachmentChange}
isMultiple
isFile
isLoading={isSubmitting}
loadingLabel="در حال ثبت درخواست..."
/>
{touched.attachments && errors.attachments ? (
<Error errorText={String(errors.attachments)} />
) : null}
</div> </div>
<div className="flex"> <div className="flex">
<div className="flex-1" /> <div className="flex-1" />
<div className="flex flex-1 gap-4"> <div className="flex flex-1 gap-4">
<div className="w-[250px]"> <div className="w-[250px]">
<Input <Input label="قیمت به ازای هر صفحه" value={`${PRICE_PER_PAGE.toLocaleString("fa-IR")} تومان`} readOnly />
label="قیمت به ازای هر صفحه"
value={`${PRICE_PER_PAGE.toLocaleString("fa-IR")} تومان`}
readOnly
/>
</div> </div>
<Input <Input label="مبلغ قابل پرداخت برای شما" value={`${totalPrice.toLocaleString("fa-IR")} تومان`} readOnly />
label="مبلغ قابل پرداخت برای شما"
value={`${totalPrice.toLocaleString("fa-IR")} تومان`}
readOnly
/>
</div> </div>
</div> </div>
@@ -129,14 +82,39 @@ const DesignerRequestFormFields: FC = () => {
); );
}; };
const DesignerRequestForm: FC<Props> = ({ onSubmit }) => ( const DesignerRequestForm: FC = () => {
<Formik const navigate = useNavigate();
initialValues={designerRequestInitialValues} const { mutateAsync: uploadFiles } = useMultipleUpload();
validationSchema={designerRequestValidationSchema} const { mutateAsync: initiateDesignRequest } = useInitiateDesignRequest();
onSubmit={onSubmit}
> const handleSubmit = async (values: DesignerRequestFormValues, { setSubmitting, resetForm }: FormikHelpers<DesignerRequestFormValues>) => {
let attachmentUrls: string[] = [];
if (values.attachments.length > 0) {
const uploadResponse = await uploadFiles(values.attachments);
attachmentUrls = uploadResponse.data.map((item) => item.url);
}
await initiateDesignRequest(toDesignRequestParams(values, attachmentUrls), {
onSuccess: (data) => {
toast("صورت حساب با موفقیت ثبت شد", "success");
window.open(`${import.meta.env.VITE_INVOICE_URL}${data?.data?.invoiceId}`, "_blank");
setSubmitting(false);
resetForm();
navigate(Paths.designer.list);
},
onError: (error) => {
toast(extractErrorMessage(error), "error");
setSubmitting(false);
},
});
};
return (
<Formik initialValues={designerRequestInitialValues} validationSchema={designerRequestValidationSchema} onSubmit={handleSubmit}>
<DesignerRequestFormFields /> <DesignerRequestFormFields />
</Formik> </Formik>
); );
};
export default DesignerRequestForm; export default DesignerRequestForm;
@@ -1,10 +1,4 @@
import { toast } from "@/components/Toast";
import { extractErrorMessage } from "@/helpers/utils";
import { toDesignRequestParams } from "@/pages/designer/designerRequestForm";
import type { DesignerRequestFormValues } from "@/pages/designer/types/Types";
import { useMultipleUpload } from "@/pages/uploader/hooks/useUploaderData";
import { useMutation } from "@tanstack/react-query"; import { useMutation } from "@tanstack/react-query";
import type { FormikHelpers } from "formik";
import * as api from "../service/DesignerService"; import * as api from "../service/DesignerService";
export const useInitiateDesignRequest = () => { export const useInitiateDesignRequest = () => {
@@ -12,35 +6,3 @@ export const useInitiateDesignRequest = () => {
mutationFn: api.initiateDesignRequest, mutationFn: api.initiateDesignRequest,
}); });
}; };
export const useSubmitDesignRequest = () => {
const { mutateAsync: uploadFiles } = useMultipleUpload();
const { mutateAsync: initiateDesignRequest } = useInitiateDesignRequest();
return async (
values: DesignerRequestFormValues,
{ setSubmitting, resetForm }: FormikHelpers<DesignerRequestFormValues>,
) => {
try {
const attachmentUrls =
values.attachments.length > 0
? (await uploadFiles(values.attachments)).data.map((item) => item.url)
: [];
const data = await initiateDesignRequest(
toDesignRequestParams(values, attachmentUrls),
);
toast("صورت حساب با موفقیت ثبت شد", "success");
window.open(
`${import.meta.env.VITE_INVOICE_URL}${data?.data?.invoiceId}`,
"_blank",
);
resetForm();
} catch (error) {
toast(extractErrorMessage(error), "error");
} finally {
setSubmitting(false);
}
};
};