mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 21:41:57 +00:00
feat(FE): api integration production standards
This commit is contained in:
@@ -1,9 +1,54 @@
|
||||
'use client';
|
||||
|
||||
import ProductionStandardForm from '@/components/pages/master-data/production-standard/form/ProductionStandardForm';
|
||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||
import { ProductionStandardApi } from '@/services/api/master-data';
|
||||
import { useRouter, useSearchParams } from 'next/navigation';
|
||||
import useSWR from 'swr';
|
||||
|
||||
const EditProductionStandardPage = () => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
// Get Query Params
|
||||
const productionStandardId = searchParams.get('productionStandardId');
|
||||
|
||||
// Fetch Data
|
||||
const { data: productionStandard, isLoading: isLoadingProductionStandard } =
|
||||
useSWR(productionStandardId, (id: number) =>
|
||||
ProductionStandardApi.getSingle(id)
|
||||
);
|
||||
|
||||
if (!productionStandardId) {
|
||||
router.back();
|
||||
|
||||
return (
|
||||
<div className='w-full flex flex-row justify-center items-center p-4'>
|
||||
<span className='loading loading-spinner loading-xl' />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!isLoadingProductionStandard &&
|
||||
(!productionStandard || isResponseError(productionStandard))
|
||||
) {
|
||||
router.replace('/404');
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ProductionStandardForm formType='edit' />
|
||||
{isLoadingProductionStandard && (
|
||||
<span className='loading loading-spinner loading-xl' />
|
||||
)}
|
||||
{!isLoadingProductionStandard &&
|
||||
isResponseSuccess(productionStandard) && (
|
||||
<ProductionStandardForm
|
||||
formType='edit'
|
||||
initialValue={productionStandard.data}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,54 @@
|
||||
'use client';
|
||||
|
||||
import ProductionStandardForm from '@/components/pages/master-data/production-standard/form/ProductionStandardForm';
|
||||
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
|
||||
import { ProductionStandardApi } from '@/services/api/master-data';
|
||||
import { useRouter, useSearchParams } from 'next/navigation';
|
||||
import useSWR from 'swr';
|
||||
|
||||
const DetailProductionStandardPage = () => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
// Get Query Params
|
||||
const productionStandardId = searchParams.get('productionStandardId');
|
||||
|
||||
// Fetch Data
|
||||
const { data: productionStandard, isLoading: isLoadingProductionStandard } =
|
||||
useSWR(productionStandardId, (id: number) =>
|
||||
ProductionStandardApi.getSingle(id)
|
||||
);
|
||||
|
||||
if (!productionStandardId) {
|
||||
router.back();
|
||||
|
||||
return (
|
||||
<div className='w-full flex flex-row justify-center items-center p-4'>
|
||||
<span className='loading loading-spinner loading-xl' />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!isLoadingProductionStandard &&
|
||||
(!productionStandard || isResponseError(productionStandard))
|
||||
) {
|
||||
router.replace('/404');
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ProductionStandardForm formType='detail' />
|
||||
{isLoadingProductionStandard && (
|
||||
<span className='loading loading-spinner loading-xl' />
|
||||
)}
|
||||
{!isLoadingProductionStandard &&
|
||||
isResponseSuccess(productionStandard) && (
|
||||
<ProductionStandardForm
|
||||
formType='detail'
|
||||
initialValue={productionStandard.data}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table';
|
||||
import { ProductionStandard } from '@/types/api/master-data/production-standard';
|
||||
import { Icon } from '@iconify/react';
|
||||
import useSWR from 'swr';
|
||||
import { productionStandardApi } from '@/services/api/master-data';
|
||||
import { ProductionStandardApi } from '@/services/api/master-data';
|
||||
import { isResponseSuccess } from '@/lib/api-helper';
|
||||
import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper';
|
||||
import { CellContext } from '@tanstack/react-table';
|
||||
@@ -80,14 +80,14 @@ const ProductionStandardTable = () => {
|
||||
isLoading: productionStandardsLoading,
|
||||
mutate: refreshProductionStandards,
|
||||
} = useSWR(
|
||||
`${productionStandardApi.basePath}`,
|
||||
productionStandardApi.getAllFetcher
|
||||
`${ProductionStandardApi.basePath}`,
|
||||
ProductionStandardApi.getAllFetcher
|
||||
);
|
||||
|
||||
const confirmationModalDeleteClickHandler = async () => {
|
||||
setIsDeleteLoading(true);
|
||||
|
||||
await productionStandardApi.delete(
|
||||
await ProductionStandardApi.delete(
|
||||
selectedProductionStandard?.id as number
|
||||
);
|
||||
refreshProductionStandards();
|
||||
@@ -100,8 +100,8 @@ const ProductionStandardTable = () => {
|
||||
return (
|
||||
<>
|
||||
<div className='flex flex-col gap-6 p-6'>
|
||||
<div className='flex flex-row gap-6 justify-end'>
|
||||
<Button href='/master-data/production-standard/add'>
|
||||
<div className='flex flex-row gap-6 justify-start'>
|
||||
<Button href='/master-data/production-standard/add' variant='outline'>
|
||||
<Icon icon='mdi:plus' /> Tambah
|
||||
</Button>
|
||||
</div>
|
||||
@@ -121,8 +121,8 @@ const ProductionStandardTable = () => {
|
||||
accessorKey: 'name',
|
||||
},
|
||||
{
|
||||
header: 'Jumlah Week',
|
||||
accessorFn: (row) => row.details.length,
|
||||
header: 'Kategori',
|
||||
accessorFn: (row) => row.project_category,
|
||||
},
|
||||
{
|
||||
header: 'Aksi',
|
||||
|
||||
+70
-41
@@ -1,41 +1,14 @@
|
||||
import * as Yup from 'yup';
|
||||
|
||||
export const ProductionStandardFormSchema = Yup.object({
|
||||
name: Yup.string().required('Nama wajib diisi!'),
|
||||
project_category: Yup.string().required('Kategori proyek wajib diisi!'),
|
||||
details: Yup.array().of(
|
||||
Yup.object({
|
||||
week: Yup.number().required('Minggu wajib diisi!'),
|
||||
production_standard_details: Yup.object({
|
||||
target_hen_day_production: Yup.number().required(
|
||||
'Produksi telur per hari wajib diisi!'
|
||||
),
|
||||
target_hen_house_production: Yup.number().required(
|
||||
'Produksi telur per kandang wajib diisi!'
|
||||
),
|
||||
target_egg_weight: Yup.number().required('Berat telur wajib diisi!'),
|
||||
target_egg_mass: Yup.number().required('Massa telur wajib diisi!'),
|
||||
}),
|
||||
standard_growth_details: Yup.object({
|
||||
target_mean_bw: Yup.number().required('Berat rata-rata wajib diisi!'),
|
||||
max_depletion: Yup.number().required('Maksimal depletion wajib diisi!'),
|
||||
min_uniformity: Yup.number().required(
|
||||
'Minimal uniformitas wajib diisi!'
|
||||
),
|
||||
feed_intake: Yup.number().required('Pengambilan makanan wajib diisi!'),
|
||||
}),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
||||
export const UpdateProductionStandardFormSchema = ProductionStandardFormSchema;
|
||||
|
||||
export type ProductionStandardFormValues = Yup.InferType<
|
||||
typeof ProductionStandardFormSchema
|
||||
>;
|
||||
|
||||
export const ProductionStandardRepeaterFormSchema = Yup.object({
|
||||
// Schema for LAYING category (production_standard_details is required)
|
||||
const LayingRepeaterFormSchema = Yup.object({
|
||||
week: Yup.number().required('Minggu wajib diisi!'),
|
||||
production_standard_uniformity_details: Yup.object({
|
||||
target_mean_bw: Yup.number().required('Berat rata-rata wajib diisi!'),
|
||||
max_depletion: Yup.number().required('Maksimal depletion wajib diisi!'),
|
||||
min_uniformity: Yup.number().required('Minimal uniformitas wajib diisi!'),
|
||||
feed_intake: Yup.number().required('Pengambilan makanan wajib diisi!'),
|
||||
}),
|
||||
production_standard_details: Yup.object({
|
||||
target_hen_day_production: Yup.number().required(
|
||||
'Produksi telur per hari wajib diisi!'
|
||||
@@ -45,18 +18,74 @@ export const ProductionStandardRepeaterFormSchema = Yup.object({
|
||||
),
|
||||
target_egg_weight: Yup.number().required('Berat telur wajib diisi!'),
|
||||
target_egg_mass: Yup.number().required('Massa telur wajib diisi!'),
|
||||
}),
|
||||
standard_growth_details: Yup.object({
|
||||
}).required(),
|
||||
});
|
||||
|
||||
// Schema for GROWING category (production_standard_details is optional)
|
||||
const GrowingRepeaterFormSchema = Yup.object({
|
||||
week: Yup.number().required('Minggu wajib diisi!'),
|
||||
production_standard_uniformity_details: Yup.object({
|
||||
target_mean_bw: Yup.number().required('Berat rata-rata wajib diisi!'),
|
||||
max_depletion: Yup.number().required('Maksimal depletion wajib diisi!'),
|
||||
min_uniformity: Yup.number().required('Minimal uniformitas wajib diisi!'),
|
||||
feed_intake: Yup.number().required('Pengambilan makanan wajib diisi!'),
|
||||
}),
|
||||
production_standard_details: Yup.object({
|
||||
target_hen_day_production: Yup.number().optional(),
|
||||
target_hen_house_production: Yup.number().optional(),
|
||||
target_egg_weight: Yup.number().optional(),
|
||||
target_egg_mass: Yup.number().optional(),
|
||||
}).optional(),
|
||||
});
|
||||
|
||||
// Explicit types for better type inference
|
||||
export type LayingRepeaterFormValues = Yup.InferType<
|
||||
typeof LayingRepeaterFormSchema
|
||||
>;
|
||||
export type GrowingRepeaterFormValues = Yup.InferType<
|
||||
typeof GrowingRepeaterFormSchema
|
||||
>;
|
||||
|
||||
// Union type for repeater form values
|
||||
export type ProductionStandardRepeaterFormSchemaValues =
|
||||
| LayingRepeaterFormValues
|
||||
| GrowingRepeaterFormValues;
|
||||
|
||||
// Dynamic schema factory for repeater form based on project category
|
||||
export const createProductionStandardRepeaterFormSchema = (
|
||||
category: string
|
||||
) => {
|
||||
// For LAYING category, production_standard_details is required
|
||||
if (category === 'LAYING') {
|
||||
return LayingRepeaterFormSchema;
|
||||
}
|
||||
|
||||
// For GROWING category, production_standard_details is optional
|
||||
return GrowingRepeaterFormSchema;
|
||||
};
|
||||
|
||||
// Dynamic schema factory for main form based on project category
|
||||
export const createProductionStandardFormSchema = (category: string) => {
|
||||
return Yup.object({
|
||||
name: Yup.string().required('Nama wajib diisi!'),
|
||||
project_category: Yup.string().required('Kategori proyek wajib diisi!'),
|
||||
details: Yup.array().of(
|
||||
createProductionStandardRepeaterFormSchema(category)
|
||||
),
|
||||
});
|
||||
};
|
||||
|
||||
// Static schemas for backward compatibility (default to LAYING)
|
||||
export const ProductionStandardFormSchema =
|
||||
createProductionStandardFormSchema('LAYING');
|
||||
|
||||
export const UpdateProductionStandardFormSchema = ProductionStandardFormSchema;
|
||||
|
||||
export type ProductionStandardFormValues = Yup.InferType<
|
||||
typeof ProductionStandardFormSchema
|
||||
>;
|
||||
|
||||
export const ProductionStandardRepeaterFormSchema = LayingRepeaterFormSchema;
|
||||
|
||||
export const UpdateProductionStandardRepeaterFormSchema =
|
||||
ProductionStandardRepeaterFormSchema;
|
||||
|
||||
export type ProductionStandardRepeaterFormSchemaValues = Yup.InferType<
|
||||
typeof ProductionStandardRepeaterFormSchema
|
||||
>;
|
||||
|
||||
+888
-490
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,34 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Standar Uniformity A",
|
||||
"project_category": "LAYING",
|
||||
"created_user": {
|
||||
"id": 1,
|
||||
"id_user": 1,
|
||||
"email": "admin@mbugroup.id",
|
||||
"name": "Super Admin"
|
||||
},
|
||||
"details": [
|
||||
{
|
||||
"week": 1,
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 55,
|
||||
"max_depletion": 3,
|
||||
"min_uniformity": 60,
|
||||
"feed_intake": 25
|
||||
},
|
||||
"egg_production_standard_detail": {
|
||||
"id": 1,
|
||||
"target_hen_day_production": 1,
|
||||
"target_hen_house_production": 1,
|
||||
"target_egg_weight": 1,
|
||||
"target_egg_mass": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"name": "Standard Growing 2024",
|
||||
@@ -13,7 +43,8 @@
|
||||
"details": [
|
||||
{
|
||||
"week": 13,
|
||||
"production_standard_uniformity_details": {
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 1608,
|
||||
"max_depletion": 2.217125905431294,
|
||||
"min_uniformity": 82.53307938674605,
|
||||
@@ -38,13 +69,15 @@
|
||||
"details": [
|
||||
{
|
||||
"week": 7,
|
||||
"production_standard_details": {
|
||||
"egg_production_standard_detail": {
|
||||
"id": 1,
|
||||
"target_hen_day_production": 88.75664879714013,
|
||||
"target_hen_house_production": 88.14547241912292,
|
||||
"target_egg_weight": 56.500738261325466,
|
||||
"target_egg_mass": 51.3608296108157
|
||||
},
|
||||
"standard_growth_details": {
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 1630,
|
||||
"max_depletion": 1.4984809075731345,
|
||||
"min_uniformity": 89.58032440497733,
|
||||
@@ -69,13 +102,15 @@
|
||||
"details": [
|
||||
{
|
||||
"week": 5,
|
||||
"production_standard_details": {
|
||||
"egg_production_standard_detail": {
|
||||
"id": 1,
|
||||
"target_hen_day_production": 96.61629851755295,
|
||||
"target_hen_house_production": 92.28797293699245,
|
||||
"target_egg_weight": 56.58098085770421,
|
||||
"target_egg_mass": 52.43691607207049
|
||||
},
|
||||
"production_standard_uniformity_details": {
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 1879,
|
||||
"max_depletion": 2.627489091697176,
|
||||
"min_uniformity": 82.66289615405532,
|
||||
@@ -100,13 +135,15 @@
|
||||
"details": [
|
||||
{
|
||||
"week": 19,
|
||||
"production_standard_details": {
|
||||
"egg_production_standard_detail": {
|
||||
"id": 1,
|
||||
"target_hen_day_production": 90.64987149673148,
|
||||
"target_hen_house_production": 84.72381158749832,
|
||||
"target_egg_weight": 52.66407930502588,
|
||||
"target_egg_mass": 48.67508874158
|
||||
},
|
||||
"production_standard_uniformity_details": {
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 1640,
|
||||
"max_depletion": 1.0327075188137618,
|
||||
"min_uniformity": 81.06885977450052,
|
||||
@@ -131,13 +168,15 @@
|
||||
"details": [
|
||||
{
|
||||
"week": 18,
|
||||
"production_standard_details": {
|
||||
"egg_production_standard_detail": {
|
||||
"id": 1,
|
||||
"target_hen_day_production": 93.92688146007806,
|
||||
"target_hen_house_production": 88.99021279347687,
|
||||
"target_egg_weight": 52.34548967695446,
|
||||
"target_egg_mass": 47.022424468842786
|
||||
},
|
||||
"production_standard_uniformity_details": {
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 1613,
|
||||
"max_depletion": 1.4131114163932998,
|
||||
"min_uniformity": 87.70472314168066,
|
||||
@@ -162,7 +201,8 @@
|
||||
"details": [
|
||||
{
|
||||
"week": 10,
|
||||
"production_standard_uniformity_details": {
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 1679,
|
||||
"max_depletion": 1.6915361117048733,
|
||||
"min_uniformity": 86.90679412785661,
|
||||
@@ -187,13 +227,15 @@
|
||||
"details": [
|
||||
{
|
||||
"week": 17,
|
||||
"production_standard_details": {
|
||||
"egg_production_standard_detail": {
|
||||
"id": 1,
|
||||
"target_hen_day_production": 80.64302567936814,
|
||||
"target_hen_house_production": 89.82086172466285,
|
||||
"target_egg_weight": 55.226688911717915,
|
||||
"target_egg_mass": 53.11072600271201
|
||||
},
|
||||
"production_standard_uniformity_details": {
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 1874,
|
||||
"max_depletion": 2.438323895989795,
|
||||
"min_uniformity": 84.30289784580617,
|
||||
@@ -218,13 +260,15 @@
|
||||
"details": [
|
||||
{
|
||||
"week": 13,
|
||||
"production_standard_details": {
|
||||
"egg_production_standard_detail": {
|
||||
"id": 1,
|
||||
"target_hen_day_production": 82.2346989800578,
|
||||
"target_hen_house_production": 90.75391628121226,
|
||||
"target_egg_weight": 57.499497168597166,
|
||||
"target_egg_mass": 47.20514521984387
|
||||
},
|
||||
"production_standard_uniformity_details": {
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 1831,
|
||||
"max_depletion": 1.074492532699157,
|
||||
"min_uniformity": 85.74444671505677,
|
||||
@@ -249,13 +293,15 @@
|
||||
"details": [
|
||||
{
|
||||
"week": 2,
|
||||
"production_standard_details": {
|
||||
"egg_production_standard_detail": {
|
||||
"id": 1,
|
||||
"target_hen_day_production": 90.49925722287992,
|
||||
"target_hen_house_production": 89.55923007437376,
|
||||
"target_egg_weight": 58.22187327861563,
|
||||
"target_egg_mass": 54.45919757347778
|
||||
},
|
||||
"production_standard_uniformity_details": {
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 1809,
|
||||
"max_depletion": 2.2870196905499673,
|
||||
"min_uniformity": 83.61968975899043,
|
||||
@@ -280,7 +326,8 @@
|
||||
"details": [
|
||||
{
|
||||
"week": 17,
|
||||
"production_standard_uniformity_details": {
|
||||
"growth_standard_detail": {
|
||||
"id": 1,
|
||||
"target_mean_bw": 1803,
|
||||
"max_depletion": 2.3862272943774725,
|
||||
"min_uniformity": 88.37012562585544,
|
||||
@@ -291,4 +338,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -147,24 +147,8 @@ export const FlockApi = new BaseApiService<
|
||||
UpdateFlockPayload
|
||||
>('/master-data/flocks');
|
||||
|
||||
export class ProductionStandardApi extends BaseApiService<
|
||||
export const ProductionStandardApi = new BaseApiService<
|
||||
ProductionStandard,
|
||||
unknown,
|
||||
unknown
|
||||
> {
|
||||
constructor(basePath: string) {
|
||||
super(basePath);
|
||||
}
|
||||
|
||||
async getAllFetcher() {
|
||||
return await getDummyAllFetcher();
|
||||
}
|
||||
|
||||
async getSingleFetcher(id: number) {
|
||||
return await getDummySingleFetcher(id);
|
||||
}
|
||||
}
|
||||
|
||||
export const productionStandardApi = new ProductionStandardApi(
|
||||
'/master-data/production-standard'
|
||||
);
|
||||
>('/master-data/production-standards');
|
||||
|
||||
+42
-4
@@ -12,8 +12,8 @@ export interface ProductionStandard {
|
||||
|
||||
export interface StandardDetails {
|
||||
week: number;
|
||||
standard_growth_details: StandardGrowthDetails;
|
||||
production_standard_details: ProductionStandardDetails;
|
||||
growth_standard_detail: StandardGrowthDetails;
|
||||
egg_production_standard_detail: ProductionStandardDetails;
|
||||
}
|
||||
|
||||
export interface ProductionStandardDetails {
|
||||
@@ -27,7 +27,45 @@ export interface StandardGrowthDetails {
|
||||
target_mean_bw: number;
|
||||
max_depletion: number;
|
||||
min_uniformity: number;
|
||||
max_cv: number;
|
||||
week: number;
|
||||
feed_intake: number;
|
||||
}
|
||||
|
||||
export interface CreateProductionStandardPayload {
|
||||
name: string;
|
||||
project_category: string;
|
||||
details: {
|
||||
week: number;
|
||||
growth_standard_detail: {
|
||||
target_mean_bw: number;
|
||||
max_depletion: number;
|
||||
min_uniformity: number;
|
||||
feed_intake: number;
|
||||
};
|
||||
egg_production_standard_detail: {
|
||||
target_hen_day_production: number;
|
||||
target_hen_house_production: number;
|
||||
target_egg_weight: number;
|
||||
target_egg_mass: number;
|
||||
};
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface UpdateProductionStandardPayload {
|
||||
name: string;
|
||||
project_category: string;
|
||||
details: {
|
||||
week: number;
|
||||
growth_standard_detail: {
|
||||
target_mean_bw: number;
|
||||
max_depletion: number;
|
||||
min_uniformity: number;
|
||||
feed_intake: number;
|
||||
};
|
||||
egg_production_standard_detail: {
|
||||
target_hen_day_production: number;
|
||||
target_hen_house_production: number;
|
||||
target_egg_weight: number;
|
||||
target_egg_mass: number;
|
||||
};
|
||||
}[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user