before tehran

This commit is contained in:
mohammad javad fesahat committed 2024-08-24 08:31:05 +03:30
1 parent 9ec52e4feb
commit 9804625270
206 files changed
+13627 -287

No files matched your search

+468
View File
@@ -0,0 +1,468 @@
'use client'
import Link from 'next/link'
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
import { Label } from "@/components/ui/label"
import { useEffect, useState } from 'react'
import { Button } from '@/components/ui/button'
import LSearchCustomers from '../components/l-search-customers'
import axiosInstance from '@/axios/axiosInstance'
import { useQuery, useQueryClient } from '@tanstack/react-query'
import * as z from "zod"
import { useRouter } from 'next/navigation'
import { IoMdArrowRoundBack } from "react-icons/io";
import { AlertCircle } from "lucide-react"
import {
Alert,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert"
import { ILead } from './interfaces'
import { toast } from "sonner"
import { FaFaceGrinStars, FaFaceMeh, FaFaceFrown, FaFaceSmile } from "react-icons/fa6";
import { TbTargetArrow } from "react-icons/tb";
import { HiBellAlert } from "react-icons/hi2";
import { useForm, Controller, SubmitHandler } from "react-hook-form"
import LeadComment from '../components/lead-comment'
import LeadCommentAdd from '../components/lead-comment-add'
import RemainderModal from '../../components/ui/reminder-modal'
interface IFormValues {
lead_types: [
{
id: Number,
title: String
},
],
product_types: [
{
id: Number,
name: String
},
],
lead_source: [
{
id: Number,
title: String
},
],
lead_steps: [
{
id: Number,
name: String
},
],
shahr: [
{
id: Number,
name: String
is_ostan: boolean,
"ostan": any
},
]
}
interface IShahr {
id: Number,
name: String
is_ostan: boolean,
"ostan": any
}
interface IFormNewLead {
title: string,
customer_id: number,
desc: string,
product_type_id: number ,
lead_type_id: number,
lead_source_id: number,
ostan: number,
city_id: number,
lead_step_id: number,
}
const formSchema = z.object({
title: z.string().min(5, {
message: "Username must be at least 2 characters.",
}),
})
const LeadIdPage = ({params}:{params: {id: number} })=>{
const [remainderModalHidden, setRemainderModalHidden] = useState<boolean>(true)
const [cSearchOpen, setCSearchOpen] = useState<boolean>(false)
const [statusButtonState, setStatusButtonState] = useState<{su:boolean, fa:boolean, un: boolean}>({su:false, fa:false, un: false})
const [customerName, setCustomerName] = useState<any>()
const [formValues, setFormValues] = useState<IFormValues | null>(null)
const [shahr, setShahr] = useState<IShahr[] | []>([])
const [leadForm, setLeadForm] = useState<IFormNewLead | null>(null)
const [submitButtonEnable, setSubmitButtonEnable] = useState<boolean>(true)
const [lead, setLead] = useState<ILead | null>(null)
const router = useRouter()
useEffect(()=>{
setValue('title', lead?.title)
setValue('customer_id', lead?.customer.id)
setCustomerName(lead?.customer.name_family)
setValue('desc', lead?.desc)
setValue('product_type_id', lead?.product_type.id)
setValue('lead_type_id', lead?.type.id)
setValue('lead_source_id', lead?.source.id)
setValue('ostan', lead?.city.ostan.id)
setValue('lead_step_id', lead?.step.id)
changeOstanById(lead?.city.ostan.id, lead?.city.id)
}, [lead, ])
const {
register,
control,
handleSubmit,
watch,
setValue,
formState: { errors },
} = useForm<IFormNewLead>({
shouldFocusError: false,
})
const onSubmit: SubmitHandler<IFormNewLead> = async (data) => {
await setSubmitButtonEnable(false)
try {
const result = await axiosInstance.patch(`lead/${lead?.id}/edit/`, data)
if(result.status == 201){
setSubmitButtonEnable(true)
queryClient.invalidateQueries({ queryKey: ['form-items-and-lead'] })
toast("ویرایش شد", {
description: "سرنخ با موفقیت ویرایش شد",
action: {
label: "بستن",
onClick: () => console.log("Undo"),
},
})
} else {
alert("خطا در ثبت")
}
} catch (error) {
console.log(error)
}
}
const onChangeStatus = async (status:string)=>{
const editStatusRs = await axiosInstance.patch(`lead/${lead?.id}/edit-status/`, {
status: status
})
if(editStatusRs.status=201){
queryClient.invalidateQueries({ queryKey: ['form-items-and-lead'] });
setTimeout(()=>{
alert("تغییر وضعیت سرنخ انجام شد");
}, 400)
}
}
const changeOstanById = async (ostan_id:any, city_id:any)=>{
const shahrha = await formValues?.shahr
if(shahrha){
const shahrF = await shahrha.filter((item, key)=>{
return item.ostan == ostan_id
})
setShahr(shahrF)
setTimeout(()=>{ setValue('city_id', city_id) }, 500)
}
}
const changeOstan = async (e:any)=>{
const ostan_id = await e.target.value
const shahrha = await formValues?.shahr
const shahr = await shahrha.filter((item, key)=>{
return item.ostan == ostan_id
})
setShahr(shahr)
setLeadForm((prevLeadForm)=>({
...prevLeadForm!,
ostan: ostan_id
}));
console.log(leadForm)
}
const queryClient = useQueryClient()
const result = useQuery({ queryKey:['form-items-and-lead'], queryFn: async ()=>{
const leadData = await axiosInstance.get(`lead/${params.id}/`)
const formData = await axiosInstance.get('lead/form-items/')
return {
leadData: leadData,
formData: formData
}
},onSuccess: async (result)=>{
await setFormValues(result.formData.data)
await setLead(result.leadData.data)
},})
if (result.isLoading){
return (<p className='text-center mt-5'>
درحال دریافت اطلاعات...
</p>)
}
return (
<div className="w-full md:w-[60%] lg:w-[70%] m-auto " dir="rtl">
<div className="bg-white rounded-md p-4 flex flex-row mt-7 mb-3 justify-between items-center">
<div className="text-md flex flex-row gap-x-2">
<span>
وضعیت سرنخ:
</span>
{lead?.status == 'SU' ? <FaFaceGrinStars size={26} color={'green'} /> : null}
{lead?.status == 'FA' ? <FaFaceFrown size={26} color={'red'} /> : null}
{lead?.status == 'UN' || null ? <FaFaceSmile size={26} color={'#757575'} /> : null}
</div>
<div className="flex flex-row gap-x-2">
<div className='flex flex-row gap-x-4 border p-2 rounded-md'>
<div onClick={()=>{onChangeStatus('SU')}} className='' onMouseLeave={()=>{ setStatusButtonState( (prev) => ({...prev, su:false}) ) }} onMouseOver={()=>{ setStatusButtonState( (prev) => ({...prev, su:true}) ) }}>
<FaFaceGrinStars size={26} color={statusButtonState.su ? 'green': '#757575'} />
</div>
<div onClick={()=>{onChangeStatus("FA")}} className='' onMouseLeave={()=>{ setStatusButtonState( (prev) => ({...prev, fa:false}) ) }} onMouseOver={()=>{ setStatusButtonState( (prev) => ({...prev, fa:true}) ) }}>
<FaFaceFrown size={26} color={statusButtonState.fa ? 'red': '#757575'} />
</div>
<div onClick={()=>{onChangeStatus("UN")}} className='' onMouseLeave={()=>{ setStatusButtonState( (prev) => ({...prev, un:false}) ) }} onMouseOver={()=>{ setStatusButtonState( (prev) => ({...prev, un:true}) ) }}>
<FaFaceSmile size={26} color={statusButtonState.un ? 'black': '#757575'} />
</div>
</div>
<div className='flex items-center flex-row gap-x-2'>
<div className='relative'>
<div onClick={()=>{setRemainderModalHidden(false)}} className='bg-gray-100 border pr-3 pl-3 pt-2 pb-2 rounded-md text-white'>
<HiBellAlert size={25} color={lead?.lead_reminder?.id ? 'red': 'black'} />
</div>
<RemainderModal
objID={lead?.id}
reminder_data={lead?.lead_reminder}
onOpenClose={setRemainderModalHidden} hidden={remainderModalHidden} />
</div>
<div onClick={()=>{router.back()}} className="bg-gray-100 border pr-3 pl-3 pt-2 pb-2 rounded-md text-white">
<IoMdArrowRoundBack color={"black"} size={"25"} />
</div>
</div>
</div>
</div>
<div className="mt-0 bg-white p-4 rounded-md mb-2">
<form onSubmit={handleSubmit(onSubmit)} className="formNewLead flex flex-col gap-y-4">
<div className='title'>
<Label htmlFor="title">عنوان سرنخ</Label>
<Input {...register("title", { required: 'عنوان ضروری است', minLength: {value: 5, message: 'عنوان مناسب تری بنویسید'} } )} id="title" />
</div>
<div className='customer relative w-full'>
<Label htmlFor="title">مشتری</Label>
<Controller
name="customer_id"
control={control}
rules={{ required: 'انتخاب مشتری ضروری است' }}
render={ ({ field: { onChange, onBlur, value, ref } }) => (
<>
<span
className="w-[100%] justify-between block border rounded-md p-2 cursor-pointer"
onClick={()=>setCSearchOpen(!cSearchOpen)}
ref={ref}
>
{customerName ? customerName : 'برای انتخاب مشتری کلیک کنید'}
</span>
<div className={`mt-1 customer-select ${cSearchOpen ? null : 'hidden'} h-auto absolute bg-white border-red-800 border w-full rounded-md p-4`}>
<LSearchCustomers onSelect={onChange} searchBoxState={setCSearchOpen} changeCustomerName={setCustomerName} />
</div>
</>
)}
/>
</div>
<div className='desc w-full'>
<Label htmlFor="desc">توضیحات</Label>
<Textarea {...register("desc", { required: 'توضیحات سرنخ ضروری است', minLength: {value: 30, message: 'توضیحات کامل تری بنویسید'} } )} id="desc" />
</div>
<div className='types grid grid-cols-3 gap-x-4 gap-y-4'>
<div className='prod-type'>
<Label htmlFor="desc">نوع محصول</Label>
<select {...register("product_type_id", { required: 'نوع محصول را انتخاب کنید'} )} className='border rounded-sm w-full h-10'>
<option value={""}>انتخاب کنید</option>
{formValues?.product_types.map((item, key)=>{
return (<option value={item.id} key={key}>{item.name}</option>)
})}
</select>
</div>
<div className='lead-type'>
<Label htmlFor="desc">نوع سرنخ</Label>
<select {...register("lead_type_id", { required: 'نوع سرنخ را انتخاب کنید'} )} className='border rounded-sm w-full h-10'>
<option value={''}>انتخاب کنید</option>
{formValues?.lead_types.map((item, key)=>{
return (<option value={item.id} key={key}>{item.title}</option>)
})}
</select>
</div>
<div className='lead-source'>
<Label htmlFor="desc">منبع سرنخ</Label>
<select {...register("lead_source_id", { required: 'منبع سرنخ را انتخاب کنید'} )} className='border rounded-sm w-full h-10'>
<option value={''} >انتخاب کنید</option>
{formValues?.lead_source.map((item, key)=>{
return (<option value={item.id} key={key}>{item.title}</option>)
})}
</select>
</div>
<div className='ostan'>
<Label htmlFor="desc">استان</Label>
<select {...register("ostan", { required: false} )} onChange={(e:any)=>{changeOstan(e)}} className='border rounded-sm w-full h-10'>
<option>انتخاب کنید</option>
{formValues?.shahr.map((item, key)=>{
if(item.is_ostan==true){
return (<option value={item.id} key={key}>{item.name}</option>)
}
})}
</select>
</div>
<div className='shahr'>
<Label htmlFor="desc">شهر</Label>
<select {...register("city_id", { required: 'شهر را انتخاب کنید'} )} className='border rounded-sm w-full h-10'>
<option value={''}>انتخاب کنید</option>
{shahr.map((item, key)=>{
return (<option value={item.id} key={key}>{item.name}</option>)
})}
</select>
</div>
<div className='lead-step'>
<Label htmlFor="desc">مرحله</Label>
<select {...register("lead_step_id", { required: 'مرحله سرنخ را مشخص کنید'} )} className='border rounded-sm w-full h-10'>
<option value={''}>انتخاب کنید</option>
{formValues?.lead_steps.map((item, key)=>{
return (<option value={item.id} key={key}>{item.name}</option>)
})}
</select>
</div>
</div>
{ Object.keys(errors).length ? (
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertTitle>خطا</AlertTitle>
<AlertDescription>
{Object.keys(errors).map((item, key)=>{
return <p key={key}>{errors[item]?.message}</p>
})}
</AlertDescription>
</Alert>
) : null}
<div className='flex flex-row justify-center mt-4'>
{!submitButtonEnable ? (<p className='text-center text-red-600'>در حال ثبت اطلاعات....</p>) : (
<input disabled={submitButtonEnable ? false : true } onClick={()=>{ console.log(Object.keys(errors)) } } className={'bg-gray-400 text-white pr-4 pl-4 pt-2 pb-2 rounded-md'} type='submit' value={'ویرایش'} />
)}
</div>
</form>
</div>
<div className='flex flex-col w-full border-b-[1px] border-gray-400 pb-2 mb-4'>
<LeadCommentAdd lead_id={lead?.id} />
</div>
<div className='flex flex-col gap-y-2'>
{lead?.lead_comment.map((item, key)=>{
return <LeadComment data={item} key={key} />
})}
</div>
</div>
)
}
export default LeadIdPage