Compare commits

...

4 Commits

Author SHA1 Message Date
victorAnumudu 45ba601c11 added product update endpoint 2025-10-08 17:39:12 +01:00
CHIEFSOFT\ameye 0f65bc24b0 layout fix 2025-10-08 11:45:10 -04:00
ameye c9048cdbd3 Merge branch 'signup-refresh' of MERMS/MermsFirstOffice into master 2025-10-08 10:12:56 +00:00
CHIEFSOFT\ameye 94f6e55a7d Router link missing 2025-10-07 15:23:54 -04:00
3 changed files with 186 additions and 159 deletions
+46 -38
View File
@@ -1,45 +1,53 @@
import {useMutation, useQueryClient} from '@tanstack/react-query' import {useMutation, useQueryClient} from '@tanstack/react-query'
import {Formik, Form} from 'formik' import {Formik, Form} from 'formik'
import * as Yup from "yup"; import * as Yup from "yup";
import InputText from '../InputText' // import InputText from '../InputText'
import {addCustomTemplate} from '../../services/siteServices' import {updateProduct} from '../../services/siteServices'
import queryKeys from '../../services/queryKeys'; // import queryKeys from '../../services/queryKeys';
const initialValues = {
custom_id: "",
provision_name: "",
};
// To get the validation schema // To get the validation schema
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
custom_id: Yup.string().required("custom_id is required").min(6, 'must be upto 6 characters').max(25, 'must not exceed 25 characters'), details: Yup.string().required("details text is required").min(6, 'must be upto 6 characters').max(500, 'must not exceed 500 characters'),
provision_name: Yup.string().required("provision_name is required").min(6, 'must be upto 6 characters').max(200, 'must not exceed 200 characters'), sale_text: Yup.string().required("sales text is required").min(6, 'must be upto 6 characters').max(500, 'must not exceed 500 characters'),
}); });
export default function ProductDetails() { export default function ProductDetails({productDetails}) {
const initialValues = {
details: productDetails?.details,
sale_text: productDetails?.sale_text,
};
const queryClient = useQueryClient() const queryClient = useQueryClient()
const customTemplate = useMutation({ const productUpdate = useMutation({
mutationFn: (fields) => { mutationFn: (fields) => {
if (!fields.custom_id || !fields.provision_name) { return updateProduct(fields)
throw new Error('Please provide all fields marked *')
}
return addCustomTemplate(fields)
}, },
onSuccess: () => { onSuccess: () => {
queryClient.refetchQueries({ // queryClient.refetchQueries({
queryKey: [...queryKeys.custom_template], // queryKey: [...queryKeys.custom_template],
// type: 'active', // // type: 'active',
// exact: true, // // exact: true,
}) // })
}, },
onSettled: ()=>{
setTimeout(()=>{
productUpdate.reset()
}, 3000)
}
}) })
//FUNCTION TO HANDLE ADD TEMPLATE //FUNCTION TO HANDLE ADD TEMPLATE
const handleSubmit = (values, helper) => { const handleSubmit = (values, helper) => {
// customTemplate.mutate(values) const reqData = {
details: values.details,
product_detail_id: productDetails?.product_detail_id,
product_id: productDetails?.product_id,
sale_text: values.sale_text,
}
productUpdate.mutate(reqData)
}; };
return ( return (
@@ -54,50 +62,50 @@ export default function ProductDetails() {
className='flex flex-col w-full bg-white dark:bg-black-box text-black-body dark:text-white-body rounded-xl p-16 sm:px-20 sm:py-16 shadow'> className='flex flex-col w-full bg-white dark:bg-black-box text-black-body dark:text-white-body rounded-xl p-16 sm:px-20 sm:py-16 shadow'>
<div className='w-full flex flex-col gap-4'> <div className='w-full flex flex-col gap-4'>
<div className='relative text-input flex flex-col sm:flex-row gap-2 sm:items-center'> <div className='relative text-input flex flex-col sm:flex-row gap-2 sm:items-center'>
<label className={`text-base min-w-36 text-end sm:text-left ${(props.errors.custom_id && props.touched.custom_id) && 'text-red-500'}`}> <label className={`text-base min-w-36 text-end sm:text-left ${(props.errors.details && props.touched.details) && 'text-red-500'}`}>
Details Details
</label> </label>
<textarea <textarea
className='p-4 w-full resize-none border outline-none ring-0 dark:bg-transparent dark:border-white-light' className='p-4 w-full resize-none border outline-none ring-0 dark:bg-transparent dark:border-white-light'
rows={4} rows={4}
id='custom_id' id='details'
placeholder='Enter your description text here ...' placeholder='Enter your description text here ...'
name='custom_id' name='details'
value={props.values.custom_id} value={props.values.details}
handleChange={props.handleChange} onChange={props.handleChange}
/> />
</div> </div>
<div className='relative text-input flex flex-col sm:flex-row gap-2 sm:items-center'> <div className='relative text-input flex flex-col sm:flex-row gap-2 sm:items-center'>
<label className={`text-base min-w-36 text-end sm:text-left ${(props.errors.provision_name && props.touched.provision_name) && 'text-red-500'}`}> <label className={`text-base min-w-36 text-end sm:text-left ${(props.errors.sale_text && props.touched.sale_text) && 'text-red-500'}`}>
Sales Text Sales Text
</label> </label>
<textarea <textarea
className='p-4 w-full resize-none border outline-none ring-0 dark:bg-transparent dark:border-white-light' className='p-4 w-full resize-none border outline-none ring-0 dark:bg-transparent dark:border-white-light'
rows={4} rows={4}
id='provision_name' id='sale_text'
placeholder='Enter your description text here ...' placeholder='Enter your description text here ...'
name='provision_name' name='sale_text'
value={props.values.provision_name} value={props.values.sale_text}
handleChange={props.handleChange} onChange={props.handleChange}
/> />
</div> </div>
<div className='h-10 my-5 text-end'> <div className='h-10 my-5 text-end'>
<button type='submit' disabled={customTemplate.isPending} <button type='submit' disabled={productUpdate.isPending}
className='px-4 h-full bg-primary text-white font-bold rounded-md'>{customTemplate.isPending ? 'loading...' : 'Update'}</button> className='px-4 h-full bg-primary text-white font-bold rounded-md'>{productUpdate.isPending ? 'loading...' : 'Update'}</button>
</div> </div>
{customTemplate.error && {productUpdate.error &&
<> <>
<div className="w-full text-center"> <div className="w-full text-center">
<p className='text-red-500 text-sm'>{customTemplate.error.message}</p> <p className='text-red-500 text-sm'>{productUpdate.error.message}</p>
</div> </div>
</> </>
} }
{customTemplate.isSuccess && {productUpdate.isSuccess &&
<> <>
<div className="w-full text-center"> <div className="w-full text-center">
<p className='text-emerald-500 text-sm'>{'Template Added'}</p> <p className='text-emerald-500 text-sm'>{'Product Details Updated'}</p>
</div> </div>
</> </>
} }
+132 -121
View File
@@ -5,6 +5,8 @@ import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query'
import queryKeys from '../../services/queryKeys' import queryKeys from '../../services/queryKeys'
import { getProductView } from "../../services/siteServices"; import { getProductView } from "../../services/siteServices";
import ProductDetails from './ProductDetails'; import ProductDetails from './ProductDetails';
import RouteLinks from './../../RouteLinks'
import getDateTimeFromDateString from '../../helpers/getDateTimeFromDateString';
export default function ProductView() { export default function ProductView() {
@@ -29,134 +31,143 @@ export default function ProductView() {
}, },
staleTime: 0 // 0 mins staleTime: 0 // 0 mins
}) })
const countryData = data?.data // PRODUCT VIEW LIST const productConfig = data?.data?.product_configuration // PRODUCT CONFIG
console.log('DATA', countryData) const productDetails = data?.data?.product_details // PRODUCT DETAILS
return ( return (
<div className='w-full flex flex-col gap-8'> <div className='w-full flex flex-col gap-8'>
<BreadcrumbCom title={`Product View [${state?.productID}]`} paths={['Dashboard', 'Product View']}/> <BreadcrumbCom title={`Product View [${state?.productID}]`} paths={['Dashboard', 'Product View']}/>
{isFetching ?
<div className='flex flex-col gap-4'> <>
<div className='flex flex-col gap-2'> <p className='text-slate-800'>Loading...</p>
<p className='text-lg dark:text-white-light'>Product Configuration</p> </>
<div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'> : isError ?
<p className='text-red-500'>{error.message}</p>
<table className="py-2 w-full text-sm"> :
<thead className="py-2 text-sm text-slate-500 text-left"> <div className='flex flex-col gap-4'>
<tr>
<th scope="col" className="px-2 py-2" style={{width: '150px'}}>
Item
</th>
<th scope="col" className="px-2">
Value
</th>
</tr>
</thead>
<tbody>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
ProductID
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
P000008
</div>
</td>
</tr>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
ProductID
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
P000008
</div>
</td>
</tr>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
ProductID
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
P000008
</div>
</td>
</tr>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
ProductID
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
P000008
</div>
</td>
</tr>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
ProductID
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
P000008
</div>
</td>
</tr>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
ProductID
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
P000008
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div className='box bg-[aliceblue] dark:bg-black-box text-black-body dark:text-white-body'>
<div className='flex flex-col gap-2'> <div className='flex flex-col gap-2'>
<p className='text-lg'>Product Details</p> <p className='text-lg dark:text-white-light'>Product Configuration</p>
<ProductDetails /> <div className='box bg-white dark:bg-black-box text-black-body dark:text-white-body'>
<table className="py-2 w-full text-sm">
<thead className="py-2 text-sm text-slate-500 text-left">
<tr>
<th scope="col" className="px-2 py-2" style={{width: '150px'}}>
Item
</th>
<th scope="col" className="px-2">
Value
</th>
</tr>
</thead>
<tbody>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
ProductID
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
{productConfig?.product_id}
</div>
</td>
</tr>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
Description
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
{productConfig?.description}
</div>
</td>
</tr>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
Status
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
{productConfig?.status}
</div>
</td>
</tr>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
Added
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
{getDateTimeFromDateString(productConfig?.added)}
</div>
</td>
</tr>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
Banner
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
{productConfig?.banner}
</div>
</td>
</tr>
<tr className="py-2 border-t border-dashed border-slate-300">
<td className="px-2 py-2">
<div
className='w-full min-w-48 flex items-center gap-2 whitespace-nowrap'>
<div className="text-left">
UID
</div>
</div>
</td>
<td className="px-2">
<div className="text-left">
{productConfig?.uid}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<p className='text-lg'>Product Details</p>
<ProductDetails productDetails={productDetails} />
<div className='box bg-[aliceblue] dark:bg-black-box text-black-body dark:text-white-body'>
<div className='flex flex-col gap-2'>
</div>
</div> </div>
</div> </div>
</div> }
</div> </div>
) )
} }
+8
View File
@@ -148,6 +148,14 @@ export const addCustomTemplate = (reqData) => {
return postAuxEnd('/template/custom-add', postData, false) return postAuxEnd('/template/custom-add', postData, false)
} }
// FUNCTION TO ADD CUSTOM TEMPLATE
export const updateProduct = (reqData) => {
let postData = {
...reqData
}
return postAuxEnd('/product-update', postData, false)
}
// FUNCTION TO GET CUSTOM TEMPLATE DATA // FUNCTION TO GET CUSTOM TEMPLATE DATA
export const getCustomTemplate = (reqData) => { export const getCustomTemplate = (reqData) => {
const postData = { ...reqData } const postData = { ...reqData }