mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 21:41:57 +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 clsx, { ClassValue } from 'clsx';
|
||||
import { SidebarMenuItem } from '@/components/molecules/SidebarMenu';
|
||||
import { OptionType } from '@/components/input/SelectInput';
|
||||
import {
|
||||
ConstantsApiResponse,
|
||||
ProductFlagMappingUI,
|
||||
TransformedConstants,
|
||||
} from '@/types/api/constants/constants';
|
||||
|
||||
// set locale globally
|
||||
moment.locale('id');
|
||||
@@ -179,3 +185,123 @@ export function findMenuPath(
|
||||
|
||||
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