mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-25 15:55:48 +00:00
feat(FE): Add constants transformation utilities and API service
This commit is contained in:
@@ -3,6 +3,12 @@ import 'moment/locale/id';
|
|||||||
import { twMerge } from 'tailwind-merge';
|
import { twMerge } from 'tailwind-merge';
|
||||||
import clsx, { ClassValue } from 'clsx';
|
import clsx, { ClassValue } from 'clsx';
|
||||||
import { SidebarMenuItem } from '@/components/molecules/SidebarMenu';
|
import { SidebarMenuItem } from '@/components/molecules/SidebarMenu';
|
||||||
|
import { OptionType } from '@/components/input/SelectInput';
|
||||||
|
import {
|
||||||
|
ConstantsApiResponse,
|
||||||
|
ProductFlagMappingUI,
|
||||||
|
TransformedConstants,
|
||||||
|
} from '@/types/api/constants/constants';
|
||||||
|
|
||||||
// set locale globally
|
// set locale globally
|
||||||
moment.locale('id');
|
moment.locale('id');
|
||||||
@@ -179,3 +185,123 @@ export function findMenuPath(
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform a string value to OptionType with formatted label
|
||||||
|
* Example: "AYAM-AFKIR" -> { label: "Ayam Afkir", value: "AYAM-AFKIR" }
|
||||||
|
*/
|
||||||
|
export function toOption(value: string): OptionType {
|
||||||
|
return {
|
||||||
|
value,
|
||||||
|
label: formatConstantLabel(value),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format constant label by:
|
||||||
|
* 1. Replacing underscores/hyphens with spaces
|
||||||
|
* 2. Converting to title case
|
||||||
|
* 3. Handling special cases
|
||||||
|
*/
|
||||||
|
export function formatConstantLabel(value: string): string {
|
||||||
|
const specialCases: Record<string, string> = {
|
||||||
|
'PRE-STARTER': 'Pre Starter',
|
||||||
|
BOP: 'BOP',
|
||||||
|
SAPRONAK: 'SAPRONAK',
|
||||||
|
OVK: 'OVK',
|
||||||
|
DOC: 'DOC',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (specialCases[value]) {
|
||||||
|
return specialCases[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
const withSpaces = value.replace(/[-_]/g, ' ');
|
||||||
|
|
||||||
|
return formatTitleCase(withSpaces);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform product_flag_mapping from API format to UI format
|
||||||
|
*/
|
||||||
|
export function transformProductFlagMapping(
|
||||||
|
mapping: ConstantsApiResponse['product_flag_mapping']
|
||||||
|
): ProductFlagMappingUI {
|
||||||
|
return {
|
||||||
|
flags: mapping.flags.map(toOption),
|
||||||
|
options: mapping.options.map((opt) => ({
|
||||||
|
flag: toOption(opt.flag),
|
||||||
|
sub_flags: opt.sub_flags.map(toOption),
|
||||||
|
allow_without_sub_flag: opt.allow_without_sub_flag,
|
||||||
|
})),
|
||||||
|
sub_flag_to_flag: mapping.sub_flag_to_flag,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform approval workflows from API format to UI format
|
||||||
|
*/
|
||||||
|
export function transformApprovalWorkflows(
|
||||||
|
workflows: ConstantsApiResponse['approval_workflows']
|
||||||
|
) {
|
||||||
|
return workflows.map((workflow) => ({
|
||||||
|
key: workflow.key,
|
||||||
|
steps: workflow.steps.map((step) => ({
|
||||||
|
value: String(step.step_number),
|
||||||
|
label: step.step_name,
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform adjustment transaction subtypes from API format to UI format
|
||||||
|
*/
|
||||||
|
export function transformAdjustmentSubtypes(
|
||||||
|
subtypes: ConstantsApiResponse['adjustment']['transaction_subtypes']
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
RECORDING: subtypes.RECORDING.map(toOption),
|
||||||
|
PENJUALAN: subtypes.PENJUALAN.map(toOption),
|
||||||
|
PEMBELIAN: subtypes.PEMBELIAN.map(toOption),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform legacy flag aliases from API format to UI format
|
||||||
|
*/
|
||||||
|
export function transformLegacyFlagAliases(
|
||||||
|
aliases: ConstantsApiResponse['legacy_flag_aliases']
|
||||||
|
): OptionType[] {
|
||||||
|
return Object.entries(aliases).map(([key, value]) => ({
|
||||||
|
value: key,
|
||||||
|
label: formatConstantLabel(key),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform the entire constants API response to UI format
|
||||||
|
*/
|
||||||
|
export function transformConstants(
|
||||||
|
data: ConstantsApiResponse
|
||||||
|
): TransformedConstants {
|
||||||
|
return {
|
||||||
|
warehouse_types: data.warehouse_types.map(toOption),
|
||||||
|
supplier_categories: data.supplier_categories.map(toOption),
|
||||||
|
customer_supplier_types: data.customer_supplier_types.map(toOption),
|
||||||
|
adjustment: {
|
||||||
|
transaction_subtypes: transformAdjustmentSubtypes(
|
||||||
|
data.adjustment.transaction_subtypes
|
||||||
|
),
|
||||||
|
},
|
||||||
|
approval_workflows: transformApprovalWorkflows(data.approval_workflows),
|
||||||
|
flags: data.flags.map(toOption),
|
||||||
|
product_flag_mapping: transformProductFlagMapping(
|
||||||
|
data.product_flag_mapping
|
||||||
|
),
|
||||||
|
legacy_flag_aliases: transformLegacyFlagAliases(data.legacy_flag_aliases),
|
||||||
|
stock_log: {
|
||||||
|
log_types: data.stock_log.log_types.map(toOption),
|
||||||
|
transaction_types: data.stock_log.transaction_types.map(toOption),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { httpClient } from '@/services/http/client';
|
||||||
|
import {
|
||||||
|
ConstantsApiResponse,
|
||||||
|
TransformedConstants,
|
||||||
|
} from '@/types/api/constants/constants';
|
||||||
|
import { transformConstants } from '@/lib/helper';
|
||||||
|
|
||||||
|
class ConstantsApiService {
|
||||||
|
async fetchConstants(): Promise<ConstantsApiResponse | undefined> {
|
||||||
|
try {
|
||||||
|
const response = await httpClient<ConstantsApiResponse>('/constants');
|
||||||
|
return response;
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchTransformedConstants(): Promise<TransformedConstants | undefined> {
|
||||||
|
const data = await this.fetchConstants();
|
||||||
|
if (!data) return undefined;
|
||||||
|
return transformConstants(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ConstantsApi = new ConstantsApiService();
|
||||||
+86
@@ -0,0 +1,86 @@
|
|||||||
|
import { OptionType } from '@/components/input/SelectInput';
|
||||||
|
|
||||||
|
export type ApprovalWorkflowStep = {
|
||||||
|
step_number: number;
|
||||||
|
step_name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ApprovalWorkflow = {
|
||||||
|
key: string;
|
||||||
|
steps: ApprovalWorkflowStep[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ProductFlagMappingOption = {
|
||||||
|
flag: string;
|
||||||
|
sub_flags: string[];
|
||||||
|
allow_without_sub_flag: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ProductFlagMappingApiResponse = {
|
||||||
|
flags: string[];
|
||||||
|
options: ProductFlagMappingOption[];
|
||||||
|
sub_flag_to_flag: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type AdjustmentTransactionSubtypes = {
|
||||||
|
RECORDING: string[];
|
||||||
|
PENJUALAN: string[];
|
||||||
|
PEMBELIAN: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type StockLogConfig = {
|
||||||
|
log_types: string[];
|
||||||
|
transaction_types: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ConstantsApiResponse = {
|
||||||
|
warehouse_types: string[];
|
||||||
|
supplier_categories: string[];
|
||||||
|
customer_supplier_types: string[];
|
||||||
|
adjustment: {
|
||||||
|
transaction_subtypes: AdjustmentTransactionSubtypes;
|
||||||
|
};
|
||||||
|
approval_workflows: ApprovalWorkflow[];
|
||||||
|
flags: string[];
|
||||||
|
product_flag_mapping: ProductFlagMappingApiResponse;
|
||||||
|
legacy_flag_aliases: Record<string, string>;
|
||||||
|
stock_log: StockLogConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ProductFlagMappingOptionUI = {
|
||||||
|
flag: OptionType;
|
||||||
|
sub_flags: OptionType[];
|
||||||
|
allow_without_sub_flag: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ProductFlagMappingUI = {
|
||||||
|
flags: OptionType[];
|
||||||
|
options: ProductFlagMappingOptionUI[];
|
||||||
|
sub_flag_to_flag: Record<string, string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ApprovalWorkflowUI = {
|
||||||
|
key: string;
|
||||||
|
steps: OptionType[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TransformedConstants = {
|
||||||
|
warehouse_types: OptionType[];
|
||||||
|
supplier_categories: OptionType[];
|
||||||
|
customer_supplier_types: OptionType[];
|
||||||
|
adjustment: {
|
||||||
|
transaction_subtypes: {
|
||||||
|
RECORDING: OptionType[];
|
||||||
|
PENJUALAN: OptionType[];
|
||||||
|
PEMBELIAN: OptionType[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
approval_workflows: ApprovalWorkflowUI[];
|
||||||
|
flags: OptionType[];
|
||||||
|
product_flag_mapping: ProductFlagMappingUI;
|
||||||
|
legacy_flag_aliases: OptionType[];
|
||||||
|
stock_log: {
|
||||||
|
log_types: OptionType[];
|
||||||
|
transaction_types: OptionType[];
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user