Created
March 28, 2024 04:41
-
-
Save mushfiqweb/97ae0d2b990b9abc4692b3f5c4aeda62 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { BaseMsisdn } from '@/@types/product'; | |
import { SegmentItemOption } from '@/components/shared'; | |
import { Card, DatePicker, Segment, Select } from '@/components/ui'; | |
import { FormItem } from '@/components/ui/Form'; | |
import type { InputProps } from '@/components/ui/Input'; | |
import Input from '@/components/ui/Input'; | |
import CaseConversion from '@/utils/caseConversion'; | |
import { | |
useGetMsisdnDataQuery, | |
useGetProductMetaDataQuery, | |
} from '@/views/connect/Product/store/productsApi'; | |
import classNames from 'classnames'; | |
import { Field, FieldProps, FormikErrors, FormikTouched } from 'formik'; | |
import { HiCheckCircle } from 'react-icons/hi'; | |
import { MdOutlineWarning } from 'react-icons/md'; | |
type Option = { | |
label: string; | |
value: string; | |
}; | |
type FormFieldsName = { | |
sim_type: number; | |
product_code: string; | |
name: string; | |
commercial_name_en: string; | |
commercial_name_bn: string; | |
display_title_en?: string; | |
display_title_bn?: string; | |
short_description: string; | |
display_sd_vat_tax?: string; | |
vat?: number; | |
mrp_price?: number; | |
price?: number; | |
points?: number; | |
validity: number; | |
validity_unit: string; | |
renew_product_code?: string; | |
recharge_product_code?: string; | |
tags?: Option[]; | |
special_type?: string; | |
show_from?: string | Date; | |
hide_from?: string | Date; | |
base_msisdn_group_id?: string | number; | |
content_filter_tags?: string; | |
// is_visible: boolean | number; | |
}; | |
type BasicInformationFields = { | |
type: 'edit' | 'new'; | |
touched: FormikTouched<FormFieldsName>; | |
errors: FormikErrors<FormFieldsName>; | |
values: FormFieldsName; | |
}; | |
const connectionTypeSelections = [ | |
{ value: '1', label: 'Prepaid' }, | |
{ value: '2', label: 'Postpaid' }, | |
]; | |
const NumberInput = (props: InputProps) => { | |
return ( | |
<Input {...props} value={props.field.value} type="number" suffix="" /> | |
); | |
}; | |
const mapBaseMsisdn = (data: BaseMsisdn[]): Option[] => { | |
return data.map((item) => ({ | |
value: item?.id?.toString() || '', | |
label: item.title, | |
})); | |
}; | |
const BasicInformationFields = (props: BasicInformationFields) => { | |
const { | |
values = { | |
tags: [], | |
sim_type: 1, | |
validity_unit: '', | |
special_type: '', | |
base_msisdn_group_id: '', | |
}, | |
touched, | |
errors, | |
type, | |
} = props; | |
const { data: productMetaData } = useGetProductMetaDataQuery(); | |
const { data: msisdnData } = useGetMsisdnDataQuery(); | |
return ( | |
<Card className="col-span-1 shadow-sm"> | |
<h5>Basic Information</h5> | |
<p className="mb-6">Section to config basic product information</p> | |
<div className="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
{/*--- connection type ---*/} | |
{type === 'new' && ( | |
<FormItem | |
asterisk | |
className="mb-2 col-span-full" | |
label="Connection Type" | |
invalid={Boolean(errors.sim_type && touched.sim_type)} | |
errorMessage={errors.sim_type as string} | |
> | |
<Field name="sim_type"> | |
{({ field, form }: FieldProps) => ( | |
<Segment | |
className="w-full" | |
defaultValue={values.sim_type?.toString()} | |
selectionType="single" | |
onChange={(val) => | |
form.setFieldValue( | |
field.name, | |
parseInt(val.toString()) | |
) | |
} | |
> | |
<div className="grid grid-cols-2 gap-4 w-full"> | |
{connectionTypeSelections.map( | |
(connectionType) => ( | |
<Segment.Item | |
key={connectionType.value} | |
value={connectionType.value} | |
// disabled={type === 'edit'} | |
> | |
{({ | |
active, | |
onSegmentItemClick, | |
disabled, | |
}) => { | |
return ( | |
<div className="text-center"> | |
<SegmentItemOption | |
hoverable | |
active={ | |
active | |
} | |
disabled={ | |
disabled | |
} | |
defaultGutter={ | |
false | |
} | |
className="relative min-h-[40px] w-full" | |
customCheck={ | |
<HiCheckCircle className="text-indigo-600 absolute top-2 right-2 text-lg" /> | |
} | |
onSegmentItemClick={ | |
onSegmentItemClick | |
} | |
> | |
<div className="flex flex-col items-start mx-4"> | |
<h6> | |
{CaseConversion.toTitleCase( | |
connectionType.label | |
)} | |
</h6> | |
</div> | |
</SegmentItemOption> | |
</div> | |
); | |
}} | |
</Segment.Item> | |
) | |
)} | |
</div> | |
</Segment> | |
)} | |
</Field> | |
</FormItem> | |
)} | |
{/*--- product code & product name */} | |
<div className="grid grid-cols-1 md:grid-cols-2 col-span-full gap-4"> | |
{type === 'new' && ( | |
<FormItem | |
asterisk | |
className="mb-2" | |
label="Product Code" | |
invalid={ | |
(errors.product_code && | |
touched.product_code) as boolean | |
} | |
errorMessage={errors.product_code} | |
> | |
<Field | |
type="text" | |
// disabled={type === 'edit'} | |
autoComplete="off" | |
name="product_code" | |
placeholder="Product Code" | |
component={Input} | |
size="sm" | |
/> | |
</FormItem> | |
)} | |
<FormItem | |
asterisk | |
className={classNames( | |
'mb-2', | |
type === 'edit' && 'col-span-full' | |
)} | |
label="Product Name" | |
size="xs" | |
invalid={(errors.name && touched.name) as boolean} | |
errorMessage={errors.name} | |
> | |
<Field | |
type="text" | |
autoComplete="off" | |
name="name" | |
placeholder="Product Name" | |
component={Input} | |
size="sm" | |
/> | |
</FormItem> | |
</div> | |
{/*--- commercial name en & bn ---*/} | |
<div className="grid grid-cols-1 md:grid-cols-2 col-span-full gap-4"> | |
<FormItem | |
asterisk | |
className="mb-2" | |
size="xs" | |
label="Commercial Name En" | |
invalid={ | |
(errors.commercial_name_en && | |
touched.commercial_name_en) as boolean | |
} | |
errorMessage={errors.commercial_name_en} | |
> | |
<Field | |
type="text" | |
autoComplete="off" | |
name="commercial_name_en" | |
placeholder="Commercial Name En" | |
component={Input} | |
size="sm" | |
/> | |
</FormItem> | |
<FormItem | |
asterisk | |
className="mb-2" | |
size="xs" | |
label="Commercial Name Bn" | |
invalid={ | |
(errors.commercial_name_bn && | |
touched.commercial_name_bn) as boolean | |
} | |
errorMessage={errors.commercial_name_bn} | |
> | |
<Field | |
type="text" | |
autoComplete="off" | |
name="commercial_name_bn" | |
placeholder="Commercial Name Bn" | |
component={Input} | |
size="sm" | |
/> | |
</FormItem> | |
</div> | |
{/*--- display title en & bn ---*/} | |
<div className="grid grid-cols-1 md:grid-cols-2 col-span-full gap-4"> | |
<FormItem | |
className="mb-2" | |
label="Display Title En" | |
size="xs" | |
invalid={ | |
(errors.display_title_en && | |
touched.display_title_en) as boolean | |
} | |
errorMessage={errors.display_title_en} | |
> | |
<Field | |
type="text" | |
autoComplete="off" | |
name="display_title_en" | |
placeholder="Display Title En" | |
component={Input} | |
size="sm" | |
/> | |
</FormItem> | |
<FormItem | |
className="mb-2" | |
label="Display Title Bn" | |
size="xs" | |
invalid={ | |
(errors.display_title_bn && | |
touched.display_title_bn) as boolean | |
} | |
errorMessage={errors.display_title_bn} | |
> | |
<Field | |
type="text" | |
autoComplete="off" | |
name="display_title_bn" | |
placeholder="Display Title Bn" | |
component={Input} | |
size="sm" | |
/> | |
</FormItem> | |
</div> | |
{/*--- short description ---*/} | |
<FormItem | |
className="col-span-full mb-2" | |
label="Short Description" | |
labelClass="!justify-start" | |
invalid={ | |
(errors.short_description && | |
touched.short_description) as boolean | |
} | |
errorMessage={errors.short_description} | |
> | |
<Field | |
textArea | |
name="short_description" | |
placeholder="Short Description" | |
component={Input} | |
/> | |
</FormItem> | |
{/*--- display sd vat tax & vat ---*/} | |
<div className="grid grid-cols-1 md:grid-cols-2 col-span-full gap-4"> | |
<FormItem | |
className="mb-2" | |
label="Display Sd Vat Tax" | |
size="xs" | |
invalid={ | |
(errors.display_sd_vat_tax && | |
touched.display_sd_vat_tax) as boolean | |
} | |
errorMessage={errors.display_sd_vat_tax} | |
> | |
<Field | |
type="text" | |
autoComplete="off" | |
name="display_sd_vat_tax" | |
placeholder="Display Sd Vat Tax" | |
component={Input} | |
size="sm" | |
/> | |
</FormItem> | |
<FormItem | |
className="mb-0" | |
size="sm" | |
label="VAT" | |
invalid={(errors.vat && touched.vat) as boolean} | |
errorMessage={errors.vat} | |
> | |
<Field size="sm" name="vat"> | |
{({ field }: FieldProps) => { | |
return ( | |
<NumberInput | |
placeholder="VAT" | |
field={field} | |
size="sm" | |
/> | |
); | |
}} | |
</Field> | |
</FormItem> | |
</div> | |
{/*--- mrp price & price ---*/} | |
<div className="grid grid-cols-1 md:grid-cols-2 col-span-full gap-4"> | |
<FormItem | |
asterisk | |
className="mb-0" | |
label="MRP Price" | |
invalid={ | |
(errors.mrp_price && touched.mrp_price) as boolean | |
} | |
errorMessage={errors.mrp_price} | |
> | |
<Field name="mrp_price"> | |
{({ field }: FieldProps) => { | |
return ( | |
<NumberInput | |
placeholder="MRP Price" | |
field={field} | |
size="sm" | |
/> | |
); | |
}} | |
</Field> | |
</FormItem> | |
<FormItem | |
className="mb-0" | |
size="sm" | |
label="Price" | |
invalid={(errors.price && touched.price) as boolean} | |
errorMessage={errors.price} | |
> | |
<Field size="sm" name="price"> | |
{({ field, form }: FieldProps) => { | |
return ( | |
<NumberInput | |
placeholder="Price" | |
field={field} | |
size="sm" | |
/> | |
); | |
}} | |
</Field> | |
</FormItem> | |
</div> | |
{/*--- points, validity & validity unit ---*/} | |
<div className="grid grid-cols-1 md:grid-cols-3 col-span-full gap-4"> | |
<FormItem | |
size="sm" | |
className="mb-0" | |
label="Points" | |
invalid={(errors.points && touched.points) as boolean} | |
errorMessage={errors.points} | |
> | |
<Field size="sm" name="points"> | |
{({ field, form }: FieldProps) => { | |
return ( | |
<NumberInput | |
placeholder="Points" | |
field={field} | |
size="sm" | |
/> | |
); | |
}} | |
</Field> | |
</FormItem> | |
<FormItem | |
asterisk | |
size="sm" | |
className="mb-0" | |
label="Validity" | |
invalid={ | |
(errors.validity && touched.validity) as boolean | |
} | |
errorMessage={errors.validity} | |
> | |
<Field size="sm" name="validity"> | |
{({ field, form }: FieldProps) => { | |
return ( | |
<NumberInput | |
placeholder="Validity" | |
field={field} | |
size="sm" | |
/> | |
); | |
}} | |
</Field> | |
</FormItem> | |
<FormItem | |
asterisk | |
label="Validity Unit" | |
invalid={ | |
(errors.validity_unit && | |
touched.validity_unit) as boolean | |
} | |
errorMessage={errors.validity_unit} | |
size="sm" | |
className="mb-0" | |
> | |
<Field size="sm" name="validity_unit"> | |
{({ field, form }: FieldProps) => ( | |
<Select | |
size="sm" | |
field={field} | |
form={form} | |
options={ | |
productMetaData?.data | |
.validityUnitSelections | |
} | |
value={productMetaData?.data.validityUnitSelections.filter( | |
(validity_unit) => | |
validity_unit?.value?.toLowerCase() === | |
values?.validity_unit?.toLowerCase() | |
)} | |
onChange={(option) => | |
form.setFieldValue( | |
field.name, | |
option?.value | |
) | |
} | |
/> | |
)} | |
</Field> | |
</FormItem> | |
</div> | |
{/*--- auto renewable & recharge product code ---*/} | |
<div className="grid grid-cols-1 md:grid-cols-2 col-span-full gap-4"> | |
<FormItem | |
className="mb-2" | |
label="Auto Renewable Code" | |
size="sm" | |
invalid={ | |
(errors.renew_product_code && | |
touched.renew_product_code) as boolean | |
} | |
errorMessage={errors.renew_product_code} | |
> | |
<Field | |
type="text" | |
autoComplete="off" | |
name="renew_product_code" | |
placeholder="Auto Renewable Code" | |
component={Input} | |
size="sm" | |
/> | |
</FormItem> | |
<FormItem | |
className="mb-2" | |
label="Recharge Product Code" | |
size="sm" | |
invalid={ | |
(errors.recharge_product_code && | |
touched.recharge_product_code) as boolean | |
} | |
errorMessage={errors.recharge_product_code} | |
> | |
<Field | |
type="text" | |
autoComplete="off" | |
name="recharge_product_code" | |
placeholder="Recharge Product Code" | |
component={Input} | |
size="sm" | |
/> | |
</FormItem> | |
</div> | |
{/*--- tags ---*/} | |
<FormItem | |
className="col-span-full mb-2" | |
label="Tags" | |
size="sm" | |
invalid={ | |
(errors.tags && touched.tags) as unknown as boolean | |
} | |
errorMessage={errors.tags as string} | |
> | |
<Field name="tags" size="sm"> | |
{({ field, form }: FieldProps) => ( | |
<Select | |
isClearable | |
field={field} | |
form={form} | |
options={productMetaData?.data.tagSelections} | |
value={values.tags} | |
size="sm" | |
onChange={(option) => | |
form.setFieldValue(field.name, option) | |
} | |
/> | |
)} | |
</Field> | |
</FormItem> | |
{/*--- content_filter_tags ---*/} | |
<div className="grid grid-cols-1 col-span-full gap-4"> | |
<FormItem | |
className="mb-2" | |
label="Content Filter Tags" | |
invalid={ | |
(errors.content_filter_tags && | |
touched.content_filter_tags) as unknown as boolean | |
} | |
errorMessage={errors.content_filter_tags as string} | |
info="Content Filter Tags should be Comma-separated value. Example: data,toffee" | |
> | |
<Field | |
type="text" | |
autoComplete="off" | |
name="content_filter_tags" | |
placeholder="Content Filter Tags" | |
component={Input} | |
size="sm" | |
/> | |
</FormItem> | |
</div> | |
{/*--- special type ---*/} | |
<FormItem | |
label="Special Type" | |
invalid={ | |
(errors.special_type && touched.special_type) as boolean | |
} | |
errorMessage={errors.special_type} | |
size="sm" | |
className="col-span-2 mb-0" | |
> | |
<Field size="sm" name="special_type"> | |
{({ field, form }: FieldProps) => ( | |
<Select | |
isClearable | |
size="sm" | |
field={field} | |
form={form} | |
options={ | |
productMetaData?.data.specialTypeSelections | |
} | |
value={productMetaData?.data.specialTypeSelections.filter( | |
(special_type) => | |
special_type.value.toString() === | |
values?.special_type?.toString() | |
)} | |
onChange={(option) => | |
form.setFieldValue( | |
field.name, | |
option?.value?.toString() | |
) | |
} | |
/> | |
)} | |
</Field> | |
</FormItem> | |
{/*--- schedule availability ---*/} | |
<> | |
<p className="font-[600] text-sm text-inherit"> | |
Schedule Availability | |
</p> | |
<div className="grid grid-cols-1 col-span-full gap-4"> | |
<FormItem | |
layout="horizontal" | |
className="mb-0" | |
size="sm" | |
label="Show From" | |
invalid={ | |
(errors.show_from && | |
touched.show_from) as boolean | |
} | |
errorMessage={errors.show_from as string} | |
> | |
<Field size="sm" name="show_from"> | |
{({ field, form }: FieldProps) => ( | |
<DatePicker.DateTimepicker | |
disableDate={(date) => { | |
const today = new Date(); | |
today.setHours(0, 0, 0, 0); | |
return date < today; | |
}} | |
size="sm" | |
placeholder="Show From Time" | |
field={field} | |
form={form} | |
value={field.value} | |
onChange={(date) => { | |
form.setFieldValue( | |
field.name, | |
date | |
); | |
}} | |
/> | |
)} | |
</Field> | |
</FormItem> | |
<FormItem | |
layout="horizontal" | |
className="mb-0" | |
size="sm" | |
label="Hide From" | |
invalid={ | |
(errors.hide_from && | |
touched.hide_from) as boolean | |
} | |
errorMessage={errors.hide_from as string} | |
> | |
<Field size="sm" name="hide_from"> | |
{({ field, form }: FieldProps) => ( | |
<DatePicker.DateTimepicker | |
disableDate={(date) => { | |
const today = new Date(); | |
today.setHours(0, 0, 0, 0); | |
return date < today; | |
}} | |
size="sm" | |
placeholder="Hide From Time" | |
field={field} | |
form={form} | |
value={field.value} | |
onChange={(date) => { | |
form.setFieldValue( | |
field.name, | |
date | |
); | |
}} | |
/> | |
)} | |
</Field> | |
</FormItem> | |
</div> | |
</> | |
{/*----- base msisdn -----*/} | |
<div className="grid grid-cols-1 gap-4 col-span-full"> | |
<FormItem | |
className="mb-0" | |
label="Base MSISDN" | |
invalid={ | |
(errors.base_msisdn_group_id && | |
touched.base_msisdn_group_id) as boolean | |
} | |
errorMessage={errors.base_msisdn_group_id} | |
> | |
<Field size="sm" name="base_msisdn_group_id"> | |
{({ field, form }: FieldProps) => ( | |
<Select | |
isClearable | |
placeholder="No Base Msisdn Group Selected" | |
field={field} | |
form={form} | |
size="sm" | |
options={mapBaseMsisdn( | |
msisdnData?.data || [] | |
)} | |
value={mapBaseMsisdn( | |
msisdnData?.data || [] | |
).filter( | |
(group_id) => | |
group_id.value?.toString() === | |
values.base_msisdn_group_id?.toString() | |
)} | |
onChange={(option) => | |
form.setFieldValue( | |
field.name, | |
option?.value | |
) | |
} | |
/> | |
)} | |
</Field> | |
<div className="text-orange-500 flex gap-2 mt-1"> | |
<MdOutlineWarning size={20} /> | |
<span> | |
<strong>Warning:</strong> If you don't | |
select a base group, this product is available | |
for connection type-wise users. | |
</span> | |
</div> | |
</FormItem> | |
</div> | |
</div> | |
</Card> | |
); | |
}; | |
export default BasicInformationFields; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment