fix(FE): skeleton for input skenario sales order

This commit is contained in:
randy-ar
2026-02-04 15:38:03 +07:00
parent e123ca9b13
commit 09cd6395e6
5 changed files with 525 additions and 168 deletions
@@ -650,7 +650,7 @@ const SalesOrderFormModal = ({
</Button> </Button>
</RequirePermission> </RequirePermission>
</div> </div>
<div className='flex flex-1 flex-col p-4'> <div className='flex flex-1 flex-col'>
<MemoizedSalesOrderProductForm <MemoizedSalesOrderProductForm
onSubmitForm={handleAddSubmitSO} onSubmitForm={handleAddSubmitSO}
initialValues={selectedMarketingProduct ?? undefined} initialValues={selectedMarketingProduct ?? undefined}
@@ -19,6 +19,23 @@ type SalesOrderProductSchemaType = {
total_price: string | number | undefined; total_price: string | number | undefined;
vehicle_number?: string | undefined; vehicle_number?: string | undefined;
uom?: string | null | undefined; uom?: string | null | undefined;
convertion_unit?: {
value: string;
label: string;
} | null;
weight_per_convertion?: number | null | undefined;
price_per_convertion?: number | null | undefined;
marketing_type?: {
value: string;
label: string;
} | null;
total_peti?: number | null | undefined;
sisa_berat?: number | null | undefined;
price_sisa_berat?: number | null | undefined;
weeks?: {
value: number;
label: string;
} | null;
}; };
export const SalesOrderProductSchema: Yup.ObjectSchema<SalesOrderProductSchemaType> = export const SalesOrderProductSchema: Yup.ObjectSchema<SalesOrderProductSchemaType> =
@@ -59,6 +76,23 @@ export const SalesOrderProductSchema: Yup.ObjectSchema<SalesOrderProductSchemaTy
.min(1, 'Total Penjualan wajib diisi!') .min(1, 'Total Penjualan wajib diisi!')
.required('Total Penjualan wajib diisi!'), .required('Total Penjualan wajib diisi!'),
uom: Yup.string().nullable().optional().notRequired(), uom: Yup.string().nullable().optional().notRequired(),
convertion_unit: Yup.object({
value: Yup.string().required('Konversi Satuan wajib diisi!'),
label: Yup.string().required('Konversi Satuan wajib diisi!'),
}).nullable(),
weight_per_convertion: Yup.number().nullable().optional().notRequired(),
marketing_type: Yup.object({
value: Yup.string().required('Kategori Penjualan wajib diisi!'),
label: Yup.string().required('Kategori Penjualan wajib diisi!'),
}).nullable(),
price_per_convertion: Yup.number().nullable().optional().notRequired(),
total_peti: Yup.number().nullable().optional().notRequired(),
sisa_berat: Yup.number().nullable().optional().notRequired(),
price_sisa_berat: Yup.number().nullable().optional().notRequired(),
weeks: Yup.object({
value: Yup.number().required('Minggu wajib diisi!'),
label: Yup.string().required('Minggu wajib diisi!'),
}).nullable(),
}); });
export type SalesOrderProductFormValues = Yup.InferType< export type SalesOrderProductFormValues = Yup.InferType<
@@ -14,12 +14,22 @@ import { ProductWarehouseApi } from '@/services/api/inventory';
import NumberInput from '@/components/input/NumberInput'; import NumberInput from '@/components/input/NumberInput';
import Button from '@/components/Button'; import Button from '@/components/Button';
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
import { formatNumber, formatVechicleNumber } from '@/lib/helper'; import {
formatNumber,
formatTitleCase,
formatVechicleNumber,
} from '@/lib/helper';
import PatternInput from '@/components/input/PatternInput'; import PatternInput from '@/components/input/PatternInput';
import Alert from '@/components/Alert'; import Alert from '@/components/Alert';
import AlertErrorList from '@/components/helper/form/FormErrors'; import AlertErrorList from '@/components/helper/form/FormErrors';
import { useFormikErrorList } from '@/services/hooks/useFormikErrorList'; import { useFormikErrorList } from '@/services/hooks/useFormikErrorList';
import SelectInputRadio from '@/components/input/SelectInputRadio'; import SelectInputRadio from '@/components/input/SelectInputRadio';
import {
MARKETING_CONVERTION_UNIT_OPTIONS,
MARKETING_TYPE_OPTIONS,
} from '@/config/constant';
import { Icon } from '@iconify/react';
import Dropdown from '@/components/Dropdown';
const roundWeight = (value: number) => Number(value.toFixed(2)); const roundWeight = (value: number) => Number(value.toFixed(2));
const roundPrice = (value: number) => Math.round(value); const roundPrice = (value: number) => Math.round(value);
@@ -41,6 +51,7 @@ const SalesOrderProductForm = ({
const [currentInput, setCurrentInput] = useState<string>(''); const [currentInput, setCurrentInput] = useState<string>('');
const [selectedProductWarehouse, setSelectedProductWarehouse] = const [selectedProductWarehouse, setSelectedProductWarehouse] =
useState<ProductWarehouse | null>(null); useState<ProductWarehouse | null>(null);
const [hasSisaBerat, setHasSisaBerat] = useState<boolean>(false);
// ============ Formik ============ // ============ Formik ============
const formik = useFormik<SalesOrderProductFormValues>({ const formik = useFormik<SalesOrderProductFormValues>({
@@ -57,6 +68,13 @@ const SalesOrderProductForm = ({
avg_weight: initialValues?.avg_weight || '', avg_weight: initialValues?.avg_weight || '',
total_price: initialValues?.total_price || '', total_price: initialValues?.total_price || '',
uom: initialValues?.uom || '', uom: initialValues?.uom || '',
weight_per_convertion:
initialValues?.weight_per_convertion != null
? Number(initialValues.weight_per_convertion)
: null,
convertion_unit: initialValues?.convertion_unit || null,
marketing_type: initialValues?.marketing_type || null,
total_peti: initialValues?.total_peti ?? null,
}, },
validationSchema: SalesOrderProductSchema, validationSchema: SalesOrderProductSchema,
onSubmit: async (values) => { onSubmit: async (values) => {
@@ -76,6 +94,14 @@ const SalesOrderProductForm = ({
loadMore: loadMoreKandang, loadMore: loadMoreKandang,
} = useSelect<Kandang>(WarehouseApi.basePath, 'id', 'name'); } = useSelect<Kandang>(WarehouseApi.basePath, 'id', 'name');
// Options Weeks dari minggu 1 - 22
const optionsWeeks = useMemo(() => {
return Array.from({ length: 22 }, (_, i) => ({
value: i + 1,
label: `Weeks ${i + 1}`,
}));
}, []);
const { const {
options: warehouseSourceOptions, options: warehouseSourceOptions,
rawData: warehouseSourceRawData, rawData: warehouseSourceRawData,
@@ -89,6 +115,7 @@ const SalesOrderProductForm = ({
'', '',
{ {
warehouse_id: formik.values.kandang_id?.toString() ?? '', warehouse_id: formik.values.kandang_id?.toString() ?? '',
type: formik.values.marketing_type?.value.toLocaleUpperCase() ?? '',
} }
); );
@@ -279,174 +306,450 @@ const SalesOrderProductForm = ({
onSubmit={handleFormSubmit} onSubmit={handleFormSubmit}
onReset={handleResetForm} onReset={handleResetForm}
> >
{formErrorMessage && ( <div className='flex flex-col gap-1.5 p-4 border-b border-base-content/10'>
<div onClick={() => setFormErrorMessage('')} className='my-3 w-full'> {formErrorMessage && (
<Alert color='error'> <div
{formErrorMessage ? formErrorMessage : ''} onClick={() => setFormErrorMessage('')}
</Alert> className='my-3 w-full'
</div> >
)} <Alert color='error'>
<PatternInput {formErrorMessage ? formErrorMessage : ''}
name='vehicle_number' </Alert>
label='No. Polisi' </div>
format='AA #### AAA' )}
mask='_' {/* Nomor Polisi */}
inputVehicleNumber <PatternInput
required name='vehicle_number'
type='text' label='No. Polisi'
placeholder='B 1234 CDE' format='AA #### AAA'
value={formatVechicleNumber(formik.values.vehicle_number ?? '')} mask='_'
onChange={formik.handleChange} inputVehicleNumber
onBlur={formik.handleBlur} required
isError={ type='text'
formik.touched.vehicle_number && placeholder='B 1234 CDE'
Boolean(formik.errors.vehicle_number) value={formatVechicleNumber(formik.values.vehicle_number ?? '')}
} onChange={formik.handleChange}
errorMessage={formik.errors.vehicle_number} onBlur={formik.handleBlur}
/> isError={
<SelectInputRadio formik.touched.vehicle_number &&
required Boolean(formik.errors.vehicle_number)
label='Kandang' }
options={kandangSourceOptions} errorMessage={formik.errors.vehicle_number}
isLoading={isLoadingKandangSourceOptions} />
value={formik.values.kandang}
onChange={kandangChangeHandler} {/* Gudang */}
isClearable <SelectInputRadio
onInputChange={setKandangInputValue} required
onMenuScrollToBottom={loadMoreKandang} label='Gudang'
isError={ options={kandangSourceOptions}
formik.touched.kandang_id && Boolean(formik.errors.kandang_id) isLoading={isLoadingKandangSourceOptions}
} value={formik.values.kandang}
errorMessage={formik.errors.kandang_id} onChange={kandangChangeHandler}
placeholder='Pilih Kandang' isClearable
/> onInputChange={setKandangInputValue}
<SelectInputRadio onMenuScrollToBottom={loadMoreKandang}
required isError={
label='Produk' formik.touched.kandang_id && Boolean(formik.errors.kandang_id)
options={productOptionsFiltered} }
isLoading={isLoadingWarehouseSourceOptions} errorMessage={formik.errors.kandang_id}
value={formik.values.product_warehouse} placeholder='Pilih Gudang'
onChange={warehouseChangeHandler} />
onInputChange={setWarehouseInputValue}
onMenuScrollToBottom={loadMoreWarehouse} {/* Kategori */}
isClearable <SelectInputRadio
placeholder={ required
formik.values.kandang_id label='Kategori '
? productOptionsFiltered.length == 0 options={MARKETING_TYPE_OPTIONS}
? 'Tidak ada produk yang tersedia' value={formik.values.marketing_type}
: 'Pilih produk' onChange={(val) => {
: 'Pilih Kandang Terlebih Dahulu' formik.setFieldValue('marketing_type', val);
} warehouseChangeHandler(null);
isDisabled={!formik.values.kandang_id} formik.setFieldValue('product_warehouse', null);
isError={ formik.setFieldValue('product_warehouse_id', null);
formik.touched.product_warehouse_id && formik.setFieldValue('convertion_unit', null);
Boolean(formik.errors.product_warehouse_id) formik.setFieldValue('weight_per_convertion', null);
} formik.setFieldValue('total_peti', null);
errorMessage={formik.errors.product_warehouse_id} }}
/> isClearable
<NumberInput placeholder='Pilih Kategori'
required />
label='Kuantitas'
name='qty' {/* Produk */}
value={formik.values.qty} <SelectInputRadio
onChange={(e) => { required
formik.handleChange(e); label='Produk'
setCurrentInput(e.target.name); options={productOptionsFiltered}
}} isLoading={isLoadingWarehouseSourceOptions}
onBlur={() => handleBlurField('qty')} value={formik.values.product_warehouse}
isError={formik.touched.qty && Boolean(formik.errors.qty)} onChange={warehouseChangeHandler}
errorMessage={formik.errors.qty} onInputChange={setWarehouseInputValue}
placeholder='Masukan Kuantitas' onMenuScrollToBottom={loadMoreWarehouse}
endAdornment={ isClearable
<div className='flex items-center gap-2'> placeholder={
<span className='text-sm text-gray-500'> formik.values.kandang_id
{selectedProductWarehouse?.product?.uom?.name} ? productOptionsFiltered.length == 0
? 'Tidak ada produk yang tersedia'
: 'Pilih produk'
: 'Pilih Kandang Terlebih Dahulu'
}
isDisabled={!formik.values.kandang_id}
isError={
formik.touched.product_warehouse_id &&
Boolean(formik.errors.product_warehouse_id)
}
errorMessage={formik.errors.product_warehouse_id}
/>
{/* Konversi Satuan Telur */}
{formik.values.marketing_type &&
formik.values.marketing_type.value.toLowerCase() === 'telur' &&
(!formik.values.convertion_unit ||
formik.values.convertion_unit.value.toLowerCase() !== 'peti') && (
<SelectInputRadio
required
label='Tipe Konversi'
options={MARKETING_CONVERTION_UNIT_OPTIONS}
value={formik.values.convertion_unit}
onChange={(val) => formik.setFieldValue('convertion_unit', val)}
isClearable
placeholder='Pilih Konversi Satuan'
/>
)}
{formik.values.convertion_unit &&
formik.values.convertion_unit.value === 'peti' && (
<div className='flex flex-col'>
<label className='font-semibold text-xs py-2 leading-5'>
Tipe Konversi <span className='text-error'>*</span>
</label>
<div className='flex items-center gap-2 border border-base-content/10 rounded-lg pe-3 text-sm text-base-content'>
<div>
<Dropdown
align='start'
direction='bottom'
trigger={
<div className='flex flex-row items-stretch gap-2 py-1 ps-3 text-sm'>
<div className='py-1.5 flex items-center gap-2'>
{formatTitleCase(
formik.values.convertion_unit.value
)}
<Icon
icon='heroicons:chevron-down-solid'
className='my-auto'
/>
</div>
<div className='w-px border-none bg-base-content/10'></div>
</div>
}
className={{
wrapper: 'relative',
content:
'rounded-xl mt-1 border border-base-content/5 shadow-sm overflow-hidden min-w-68.5 sm:min-w-103.25 w-full',
}}
>
<ul className='rounded-lg w-full'>
{MARKETING_CONVERTION_UNIT_OPTIONS.map((option) => (
<li className='w-full' key={option.value}>
<Button
variant='ghost'
color='none'
className='w-full p-3 gap-3 font-medium justify-start text-sm text-base-content/50'
onClick={() =>
formik.setFieldValue('convertion_unit', option)
}
>
<input
type='radio'
checked={
formik.values.convertion_unit?.value ===
option.value
}
onChange={() => null}
className='radio radio-md radio-primary pointer-events-none'
/>{' '}
{option.label}
</Button>
</li>
))}
</ul>
</Dropdown>
</div>
<input
type='number'
className='w-full h-full focus:outline-none appearance-none [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none'
placeholder={`Berat ${
formik.values.convertion_unit?.value === 'peti'
? 'kg'
: ''
} per ${formik.values.convertion_unit?.value}`}
value={formik.values.weight_per_convertion ?? ''}
onChange={(e) => {
formik.setFieldValue(
'weight_per_convertion',
Number(e.target.value)
);
setCurrentInput(e.target.name);
}}
/>
</div>
</div>
)}
{/* Konversi Satuan Weeks Pullet */}
{formik.values.marketing_type?.value.toLowerCase() ===
'ayam_pullet' && (
<SelectInputRadio
required
label='Minggu'
options={optionsWeeks}
value={formik.values.weeks}
onChange={(val) => {
formik.setFieldValue('weeks', val);
}}
placeholder='Pilih Weeks'
/>
)}
{/* Total Peti */}
{formik.values.convertion_unit?.value === 'peti' && (
<NumberInput
required
label='Total Peti'
name='total_pet'
value={formik.values.total_peti ?? undefined}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('total_peti')}
isError={
formik.touched.total_peti && Boolean(formik.errors.total_peti)
}
errorMessage={formik.errors.total_peti}
placeholder='Masukan Total Peti'
endAdornment={
<div className='flex items-center gap-2'>
<span className='text-sm text-base-content/50'>Kg</span>
</div>
}
bottomLabel={`1 ${formik.values.convertion_unit?.value} = ${formik.values.weight_per_convertion ?? 0} Kg`}
/>
)}
{/* Avg. Bobot */}
{formik.values.marketing_type?.value.toLowerCase() === 'trading' ||
(formik.values.convertion_unit?.value.toLowerCase() !== 'peti' &&
formik.values.convertion_unit?.value.toLowerCase() !== 'kg' && (
<NumberInput
required
label='Avg. Bobot (Kg)'
name='avg_weight'
value={formik.values.avg_weight}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('avg_weight')}
isError={
formik.touched.avg_weight &&
Boolean(formik.errors.avg_weight)
}
errorMessage={formik.errors.avg_weight}
placeholder='Masukan Bobot Rata-rata'
/>
))}
{/* Total Bobot */}
{formik.values.marketing_type?.value.toLowerCase() !== 'trading' && (
<NumberInput
required
label='Total Bobot (Kg)'
name='total_weight'
value={formik.values.total_weight}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('total_weight')}
isError={
formik.touched.total_weight &&
Boolean(formik.errors.total_weight)
}
errorMessage={formik.errors.total_weight}
placeholder='Masukan Total Bobot'
/>
)}
{/* Kuantitas */}
<NumberInput
required
label={
formik.values.marketing_type &&
formik.values.marketing_type.value.toLowerCase() === 'telur'
? `Total Butir Telur`
: `Total Kuantitas`
}
name='qty'
value={formik.values.qty}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('qty')}
isError={formik.touched.qty && Boolean(formik.errors.qty)}
errorMessage={formik.errors.qty}
placeholder='Masukan Kuantitas'
endAdornment={
<div className='flex items-center gap-2'>
<span className='text-sm text-base-content/50'>
{selectedProductWarehouse?.product?.uom?.name}
</span>
</div>
}
bottomLabel={
isResponseSuccess(warehouseSourceRawData) &&
formik.values.product_warehouse_id
? `Stok tersedia: ${formatNumber(
warehouseSourceRawData?.data?.find(
(item) => item.id === formik.values.product_warehouse_id
)?.quantity ?? 0
)} ${selectedProductWarehouse?.product?.uom?.name}`
: ''
}
/>
{/* Harga per convertion unit */}
{(formik.values.convertion_unit?.value.toLowerCase() === 'peti' ||
formik.values.convertion_unit?.value.toLowerCase() === 'kg') && (
<NumberInput
required
label={`Harga / ${formik.values.convertion_unit?.label ?? 'Produk'} (Rp)`}
name='price_per_convertion'
value={formik.values.price_per_convertion ?? undefined}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('price_per_convertion')}
isError={
formik.touched.price_per_convertion &&
Boolean(formik.errors.price_per_convertion)
}
errorMessage={formik.errors.price_per_convertion}
placeholder='Masukan Harga Satuan'
/>
)}
{/* Harga Satuan per Uom Produk Warehouse */}
{formik.values.convertion_unit?.value.toLowerCase() !== 'peti' &&
formik.values.convertion_unit?.value.toLowerCase() !== 'kg' && (
<NumberInput
required
label={`Harga / ${selectedProductWarehouse?.product?.uom?.name ?? 'Produk'} (Rp)`}
name='unit_price'
value={formik.values.unit_price}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('unit_price')}
isError={
formik.touched.unit_price && Boolean(formik.errors.unit_price)
}
errorMessage={formik.errors.unit_price}
placeholder='Masukan Harga Satuan'
/>
)}
{/* Sisa kg diluar peti */}
{formik.values.convertion_unit?.value.toLowerCase() === 'peti' && (
<div className='flex flex-col'>
<div className='py-2 gap-3 flex items-center'>
<input
type='checkbox'
name='sisa_berat'
checked={hasSisaBerat}
onChange={() => {
setHasSisaBerat(!hasSisaBerat);
}}
onBlur={() => handleBlurField('sisa_berat')}
className='toggle toggle-primary rounded-full before:rounded-full before:bg-base-content/50 border-base-content/50 checked:border-primary checked:bg-primary checked:before:bg-base-100'
/>
<label className='text-sm text-base-content/50'>
Apakah ada sisa berat di luar peti?
</label>
</div>
<span className='text-xs text-base-content/30 leading-4 pt-1.5'>
Jika ada, masukan berat di luar peti
</span> </span>
</div> </div>
} )}
bottomLabel={
isResponseSuccess(warehouseSourceRawData) &&
formik.values.product_warehouse_id
? `Stok tersedia: ${formatNumber(
warehouseSourceRawData?.data?.find(
(item) => item.id === formik.values.product_warehouse_id
)?.quantity ?? 0
)} ${selectedProductWarehouse?.product?.uom?.name}`
: ''
}
/>
<NumberInput
required
label={`Harga / ${selectedProductWarehouse?.product?.uom?.name ?? 'Produk'} (Rp)`}
name='unit_price'
value={formik.values.unit_price}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('unit_price')}
isError={
formik.touched.unit_price && Boolean(formik.errors.unit_price)
}
errorMessage={formik.errors.unit_price}
placeholder='Masukan Harga Satuan'
/>
<NumberInput
required
label='Avg. Bobot (Kg)'
name='avg_weight'
value={formik.values.avg_weight}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('avg_weight')}
isError={
formik.touched.avg_weight && Boolean(formik.errors.avg_weight)
}
errorMessage={formik.errors.avg_weight}
placeholder='Masukan Bobot Rata-rata'
/>
<NumberInput
required
label='Total Bobot (Kg)'
name='total_weight'
value={formik.values.total_weight}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('total_weight')}
isError={
formik.touched.total_weight && Boolean(formik.errors.total_weight)
}
errorMessage={formik.errors.total_weight}
placeholder='Masukan Total Bobot'
/>
<NumberInput
required
label='Total Penjualan (Rp)'
name='total_price'
value={formik.values.total_price}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('total_price')}
isError={
formik.touched.total_price && Boolean(formik.errors.total_price)
}
errorMessage={formik.errors.total_price}
placeholder='Masukan Total Penjualan'
/>
<div className='mt-4'> {hasSisaBerat && (
<AlertErrorList formErrorList={formErrorList} onClose={close} /> <>
<NumberInput
required
label='Sisa Berat (Kg)'
name='sisa_berat'
value={formik.values.sisa_berat ?? undefined}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('sisa_berat')}
isError={
formik.touched.sisa_berat && Boolean(formik.errors.sisa_berat)
}
errorMessage={formik.errors.sisa_berat}
placeholder='Masukan Sisa Berat'
/>
<NumberInput
required
label='Harga Sisa Berat (Rp)'
name='price_sisa_berat'
value={formik.values.price_sisa_berat ?? undefined}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('price_sisa_berat')}
isError={
formik.touched.price_sisa_berat &&
Boolean(formik.errors.price_sisa_berat)
}
errorMessage={formik.errors.price_sisa_berat}
placeholder='Masukan Harga Sisa Berat'
/>
</>
)}
{/* Total Penjualan */}
<NumberInput
required
label='Total Penjualan (Rp)'
name='total_price'
value={formik.values.total_price}
onChange={(e) => {
formik.handleChange(e);
setCurrentInput(e.target.name);
}}
onBlur={() => handleBlurField('total_price')}
isError={
formik.touched.total_price && Boolean(formik.errors.total_price)
}
errorMessage={formik.errors.total_price}
placeholder='Masukan Total Penjualan'
/>
{formErrorList.length > 0 && (
<div className='mt-4'>
<AlertErrorList formErrorList={formErrorList} onClose={close} />
</div>
)}
</div> </div>
<div className='h-18' /> <div className='h-18' />
<div className='absolute w-full bottom-0 right-0'> <div className='absolute w-full bottom-0 right-0 p-4'>
<Button <Button
type='submit' type='submit'
isLoading={formik.isSubmitting} isLoading={formik.isSubmitting}
+24 -5
View File
@@ -495,16 +495,35 @@ export const FILTER_TYPE_OPTIONS = [
export const MARKETING_TYPE_OPTIONS = [ export const MARKETING_TYPE_OPTIONS = [
{ {
label: 'Ayam', label: 'Ayam Pullet',
value: 'ayam', value: 'AYAM_PULLET',
}, },
{ {
label: 'Telur', label: 'Ayam',
value: 'telur', value: 'AYAM',
}, },
{ {
label: 'Trading', label: 'Trading',
value: 'trading', value: 'TRADING',
},
{
label: 'Telur',
value: 'TELUR',
},
];
export const MARKETING_CONVERTION_UNIT_OPTIONS = [
{
label: 'Kg',
value: 'kg',
},
{
label: 'Qty',
value: 'qty',
},
{
label: 'Peti',
value: 'peti',
}, },
]; ];
+1
View File
@@ -110,6 +110,7 @@ export type BaseCreateMarketingProductPayload = {
qty: string | number | undefined; qty: string | number | undefined;
avg_weight: string | number | undefined; avg_weight: string | number | undefined;
total_price: string | number | undefined; total_price: string | number | undefined;
marketing_type: string;
}; };
/** /**