Skip to content

Commit

Permalink
Merincikan tipe data form dan menampilkan satuan barang
Browse files Browse the repository at this point in the history
  • Loading branch information
sensasi-delight committed Oct 21, 2024
1 parent 94e9def commit 110cef6
Showing 1 changed file with 130 additions and 124 deletions.
254 changes: 130 additions & 124 deletions src/app/(authenticated user)/purchases/(form)/_components/items-input.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import { Controller, useFieldArray, useFormContext } from 'react-hook-form'
// types
import type { FormValues } from '../_types/form-values'
// vendors
import { Button, Input, Link, Select, SelectItem } from '@nextui-org/react'
import { Controller, useFieldArray, useFormContext } from 'react-hook-form'
import { PlusCircleIcon, TrashIcon } from 'lucide-react'
import { ProductMovement } from '@/models/table-types/product-movement'
import db from '@/models/db'
import { useLiveQuery } from 'dexie-react-hooks'
import PageUrlEnum from '@/enums/page-url'
import db from '@/models/db'
import NextLink from 'next/link'
// locals
import PageUrlEnum from '@/enums/page-url'
import { InputAdditionalContent } from '@/components/input-additional-content'

export function ItemsInput() {
const {
control,
formState: { errors },
} = useFormContext<ProductMovement>()
watch,
} = useFormContext<FormValues>()
const { remove, fields, append } = useFieldArray({
control,
name: 'items',
rules: {
required: 'Barang harus diisi',
validate: items => {
const names = items.map(item => item.product_state.name)
const names = items.map(item => item.product_state?.name)
return new Set(names).size === names.length
? undefined
: 'Barang tidak boleh sama'
Expand All @@ -41,9 +45,7 @@ export function ItemsInput() {
variant="light"
color="success"
size="sm"
onClick={() => {
append({} as ProductMovement['items'][0])
}}>
onClick={() => append({})}>
<PlusCircleIcon className="h-5 w-5" />
</Button>
</div>
Expand All @@ -54,126 +56,130 @@ export function ItemsInput() {
</div>
)}

{fields.map((item, i) => (
<div key={i} className="flex items-center gap-3">
<Controller
control={control}
name={`items.${i}.product_state`}
rules={{ required: 'Nama biaya harus diisi' }}
render={({
field: { onChange, value, ...rest },
fieldState: { error },
}) => (
<Select
isRequired
label="Produk"
description={
!products?.length ? (
<>
Data produk tidak ditemukan.{' '}
<Link
href={PageUrlEnum.PRODUCT_CREATE}
className="clickable text-xs"
as={NextLink}>
Tambah data produk?
</Link>
</>
) : undefined
}
errorMessage={error?.message}
isInvalid={!!error}
value={value?.uuid}
onChange={({ target: { value } }) => {
const selectedProduct = products?.find(
product => product.uuid === value,
)
{fields.map((_, i) => {
const selectedProduct = watch(`items.${i}.product_state`)

if (selectedProduct) {
onChange(selectedProduct)
return (
<div key={i} className="flex items-center gap-3">
<Controller
control={control}
name={`items.${i}.product_state`}
rules={{ required: 'Nama biaya harus diisi' }}
render={({
field: { onChange, value, ...rest },
fieldState: { error },
}) => (
<Select
isRequired
label="Produk"
description={
!products?.length ? (
<>
Data produk tidak ditemukan.{' '}
<Link
href={PageUrlEnum.PRODUCT_CREATE}
className="clickable text-xs"
as={NextLink}>
Tambah data produk?
</Link>
</>
) : undefined
}
}}
{...rest}>
{(products ?? []).map(product => (
<SelectItem key={product.uuid} value={product.uuid}>
{product.name}
</SelectItem>
))}
</Select>
)}
/>
errorMessage={error?.message}
isInvalid={!!error}
value={value?.uuid}
onChange={({ target: { value } }) => {
const selectedProduct = products?.find(
product => product.uuid === value,
)

<Controller
control={control}
name={`items.${i}.qty`}
rules={{ required: 'Jumlah barang harus diisi' }}
render={({
field: { onChange, value, ...rest },
fieldState: { error },
}) => (
<Input
isRequired
label="Jumlah"
type="number"
value={value ? value.toString() : ''}
onValueChange={value => {
onChange(Number(value))
}}
endContent={
<InputAdditionalContent>
{item.product_state?.qty_unit}
</InputAdditionalContent>
}
{...rest}
isInvalid={!!error}
errorMessage={error?.message}
/>
)}
/>
if (selectedProduct) {
onChange(selectedProduct)
}
}}
{...rest}>
{(products ?? []).map(product => (
<SelectItem key={product.uuid} value={product.uuid}>
{product.name}
</SelectItem>
))}
</Select>
)}
/>

<Controller
control={control}
name={`items.${i}.price`}
rules={{ required: 'Harga beli satuan harus diisi' }}
render={({
field: { onChange, value, ...rest },
fieldState: { error },
}) => (
<Input
isRequired
label="Harga Beli Satuan"
type="number"
value={value ? value.toString() : ''}
onValueChange={value => {
onChange(Number(value))
}}
startContent={
<InputAdditionalContent>Rp</InputAdditionalContent>
}
endContent={
<InputAdditionalContent>
/{item.product_state?.qty_unit}
</InputAdditionalContent>
}
{...rest}
isInvalid={!!error}
errorMessage={error?.message}
/>
)}
/>
<Controller
control={control}
name={`items.${i}.qty`}
rules={{ required: 'Jumlah barang harus diisi' }}
render={({
field: { onChange, value, ...rest },
fieldState: { error },
}) => (
<Input
isRequired
label="Jumlah"
type="number"
value={value ? value.toString() : ''}
onValueChange={value => {
onChange(Number(value))
}}
endContent={
<InputAdditionalContent>
{selectedProduct?.qty_unit}
</InputAdditionalContent>
}
{...rest}
isInvalid={!!error}
errorMessage={error?.message}
/>
)}
/>

<Button
isIconOnly
variant="flat"
color="danger"
size="sm"
tabIndex={-1}
onClick={() => {
remove(i)
}}>
<TrashIcon />
</Button>
</div>
))}
<Controller
control={control}
name={`items.${i}.price`}
rules={{ required: 'Harga beli satuan harus diisi' }}
render={({
field: { onChange, value, ...rest },
fieldState: { error },
}) => (
<Input
isRequired
label="Harga Beli Satuan"
type="number"
value={value ? value.toString() : ''}
onValueChange={value => {
onChange(Number(value))
}}
startContent={
<InputAdditionalContent>Rp</InputAdditionalContent>
}
endContent={
<InputAdditionalContent>
/{selectedProduct?.qty_unit}
</InputAdditionalContent>
}
{...rest}
isInvalid={!!error}
errorMessage={error?.message}
/>
)}
/>

<Button
isIconOnly
variant="flat"
color="danger"
size="sm"
tabIndex={-1}
onClick={() => {
remove(i)
}}>
<TrashIcon />
</Button>
</div>
)
})}
</>
)
}

0 comments on commit 110cef6

Please sign in to comment.