CreateUpdateModel (Subscription Unlimited Design)
unknown
javascript
a year ago
14 kB
5
Indexable
'use client';
import Button from '@/components/Formik/Button';
import DragAndDropUpload from '@/components/Formik/DragAndDropUpload';
import InputField from '@/components/Formik/InputField';
import { SerializedError } from '@/features/api/apiSlice';
import { useUpdateSubscriptionMutation } from '@/features/super-admin/subscription/subscriptionApi';
import getSubDetailsObject from '@/utils/get-subscription-details-object';
import objectToFormData from '@/utils/objectToFormData';
import { FieldArray, Form, Formik } from 'formik';
import { useEffect, useState } from 'react';
import toast from 'react-hot-toast';
import { BsCheck2Circle, BsPatchCheck } from 'react-icons/bs';
import { IoCloseOutline, IoStorefrontOutline } from 'react-icons/io5';
import { LuCalendarDays, LuCircleDollarSign } from 'react-icons/lu';
import { RiTeamLine } from 'react-icons/ri';
import { TbInfinity, TbInfinityOff } from 'react-icons/tb';
import { ActionIcon, Modal, Title } from 'rizzui';
import * as Yup from 'yup';
export default function CreateUpdateModel({
setFormData,
formData,
modalState,
setModalState,
}: {
formData: any;
modalState: boolean;
setFormData: (data: any) => void;
setModalState: (state: boolean) => void;
}) {
const [isSubmitting, setIsSubmitting] = useState(false);
const [updateSubscription, { isSuccess: updateSuccess, error: updateError }] = useUpdateSubscriptionMutation();
const initialValues = {
title: formData?.title || '',
price: formData?.price || 0,
image: formData?.image || null,
allowTotalBranch: formData?.allowTotalBranch || null,
allowTotalTeamMember: formData?.allowTotalTeamMember || null,
allowTotalStamp: formData?.allowTotalStamp || null,
limit: formData?.limit || null,
descriptions: formData?.descriptions || getSubDetailsObject(false),
type: formData?.type || 'subscription',
slug: formData?.slug || '',
duration: formData?.duration || 0,
};
const validationSchema = Yup.object({
title: Yup.string().trim().required('Required!'),
price: Yup.mixed().required('Required!'),
slug: Yup.string().trim().required('Required!'),
type: Yup.mixed().oneOf(['subscription', 'addon']).required('Required!'),
allowTotalBranch: Yup.string().when('type', {
is: 'subscription',
then: () => Yup.string().required('Required!').notOneOf(['0'], 'The value 0 is not allowed!'),
otherwise: () => Yup.number().nullable(),
}),
allowTotalTeamMember: Yup.string().when('type', {
is: 'subscription',
then: () => Yup.string().required('Required!').notOneOf(['0'], 'The value 0 is not allowed!'),
otherwise: () => Yup.number().nullable(),
}),
allowTotalStamp: Yup.string().when('type', {
is: 'subscription',
then: () => Yup.string().required('Required!').notOneOf(['0'], 'The value 0 is not allowed!'),
otherwise: () => Yup.number().nullable(),
}),
limit: Yup.string().when('type', {
is: 'addon',
then: () => Yup.number().required('Required!'),
otherwise: () => Yup.number().nullable(),
}),
descriptions: Yup.string().when('type', {
is: 'subscription',
then: () =>
Yup.array()
.of(Yup.string().required('Array must contain a string'))
.min(1, 'Array must contain at least one string')
.required('Required!'),
otherwise: () => Yup.array().nullable(),
}),
});
// Submit Handler
const submitHandler = async (values: any) => {
setIsSubmitting(true);
const isFile = (obj: any): obj is File => obj instanceof File;
let objToFormData: FormData;
console.log({ values });
if (formData?._id) {
const ignoreList = [];
if (values?.type === 'subscription') {
ignoreList.push('limit');
} else {
ignoreList.push('allowTotalBranch', 'allowTotalTeamMember', 'allowTotalStamp');
}
if (!isFile(values?.image)) ignoreList.push('image');
objToFormData = objectToFormData(values, ignoreList);
updateSubscription({ id: formData._id, data: objToFormData });
}
};
// Handle Update Response
useEffect(() => {
if (updateError) {
const myError = updateError as SerializedError;
toast.error(myError?.data?.message || 'Something went wrong. Please try again!.');
setIsSubmitting(false);
}
if (updateSuccess) {
toast.success('Subscription updated successfully!');
setFormData({});
setIsSubmitting(false);
setModalState(false);
}
}, [setFormData, setModalState, updateError, updateSuccess]);
return (
<Modal isOpen={modalState} onClose={() => setModalState(true)} customSize="650px">
<div className="m-auto px-7 pb-8 pt-6">
<div className="mb-7 flex items-center justify-between">
{formData?._id ? <Title as="h4">Update A Subscription</Title> : <Title as="h4">Add New Subscription</Title>}
<ActionIcon
size="sm"
variant="text"
onClick={() => {
setModalState(false);
setFormData({});
}}
>
<IoCloseOutline className="text-2xl text-danger" />
</ActionIcon>
</div>
<div>
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={submitHandler}>
{({ values, setFieldValue }) => {
return (
<Form className="mt-5">
{formData?._id && formData?.type === 'subscription' && (
<div className="my-5 flex justify-center">
<DragAndDropUpload
value={{ name: 'image', image: values.image }}
onChange={(image: any) => setFieldValue('image', image)}
className="mt-2"
size={1024 * 1000}
sizeText="1MB"
isRounded={true}
uploadText="Upload Image"
/>
</div>
)}
<div className="flex gap-3">
<InputField name="title" label="Title" placeholder="Title" />
<InputField
name="price"
disabled={formData?.slug === 'trial' ? true : false}
label="Price (CAD)"
type="number"
placeholder="9.99"
prefix={<LuCircleDollarSign className="text-xl" />}
/>
{formData?.slug === 'trial' && (
<InputField
name="duration"
label="Duration (Days)"
type="number"
placeholder="7"
prefix={<LuCalendarDays className="text-xl" />}
/>
)}
</div>
<div className="my-3 flex gap-3">
{formData?.type === 'subscription' && (
<InputField
name="allowTotalBranch"
label="Total Branch"
type="number"
placeholder="1"
prefix={<IoStorefrontOutline className="text-xl" />}
suffix={
values.allowTotalBranch < 0 ? (
<TbInfinity
className="cursor-pointer text-xl"
title="Infinite"
onClick={() => setFieldValue('allowTotalBranch', '')}
/>
) : (
<TbInfinityOff
className="cursor-pointer text-xl"
title="Non-Infinite"
onClick={() => setFieldValue('allowTotalBranch', '-1')}
/>
)
}
disabled={values.allowTotalBranch < 0}
/>
)}
{formData?.type === 'subscription' && (
<InputField
name="allowTotalTeamMember"
label="Total Team Member"
type="number"
placeholder="1"
prefix={<RiTeamLine className="text-xl" />}
suffix={
values.allowTotalTeamMember < 0 ? (
<TbInfinity
className="cursor-pointer text-xl"
title="Infinite"
onClick={() => setFieldValue('allowTotalTeamMember', '')}
/>
) : (
<TbInfinityOff
className="cursor-pointer text-xl"
title="Non-Infinite"
onClick={() => setFieldValue('allowTotalTeamMember', '-1')}
/>
)
}
disabled={values.allowTotalTeamMember < 0}
/>
)}
{formData?.type === 'subscription' && (
<InputField
name="allowTotalStamp"
label="Total Stamp"
type="number"
placeholder="1"
prefix={<BsPatchCheck className="text-xl" />}
suffix={
values.allowTotalStamp < 0 ? (
<TbInfinity
className="cursor-pointer text-xl"
title="Infinite"
onClick={() => setFieldValue('allowTotalStamp', '')}
/>
) : (
<TbInfinityOff
className="cursor-pointer text-xl"
title="Non-Infinite"
onClick={() => setFieldValue('allowTotalStamp', '-1')}
/>
)
}
disabled={values.allowTotalStamp < 0}
/>
)}
{formData?.type !== 'subscription' && <InputField name="limit" type="number" label="Limit" placeholder="0" />}
</div>
<div className="relative mt-4 grid grid-cols-1 gap-4">
<FieldArray
name="descriptions"
render={(arrayHelpers) => (
<div>
{values?.descriptions?.map((des: any, index: number) => (
<div key={des.id} className="z-1 relative mb-4 flex items-center gap-2">
{index !== 0 && (
<div
className="absolute right-0 top-0 flex h-4 w-4 cursor-pointer items-center justify-center rounded-full bg-red-500 text-white"
onClick={() => arrayHelpers.remove(index)}
>
-
</div>
)}
<div className="flex-grow">
<div className="flex flex-col">
<InputField
label={`Description (${index + 1})`}
name={`descriptions[${index}]`}
placeholder="Write here..."
required={true}
/>
</div>
</div>
</div>
))}
<button
type="button"
className="flex cursor-pointer items-center justify-center rounded-lg bg-danger px-3 py-1 text-white"
onClick={() => arrayHelpers.push('')}
>
+ Add
</button>
</div>
)}
/>
</div>
<p className="mt-3 text-end text-xs font-semibold">
Fields marked with <span className="text-danger">*</span> are mandatory!
</p>
<p className="mt-1 text-end text-xs font-semibold">
<span className="text-danger">-1</span> indicates an <span className="text-danger">infinite</span>!
</p>
<p className="mt-1 flex items-center justify-end gap-x-1 text-xs font-semibold">
<TbInfinity className="text-base text-danger" />
<span>indicates an </span>
<span className="text-danger"> infinite sign!</span>
</p>
<p className="mt-1 flex items-center justify-end gap-x-1 text-xs font-semibold">
<TbInfinityOff className="text-base text-danger" />
<span>indicates a </span>
<span className="text-danger"> non-infinite sign!</span>
</p>
<div className="mt-6 flex justify-end">
<Button
color="danger"
type="submit"
text={formData?._id ? 'Update' : 'Submit'}
postIcon={<BsCheck2Circle className="text-base" />}
isSubmitting={isSubmitting}
/>
</div>
</Form>
);
}}
</Formik>
</div>
</div>
</Modal>
);
}
Editor is loading...
Leave a Comment