fix(resolve): resolve merge issue

This commit is contained in:
rstubryan
2025-10-29 15:56:57 +07:00
41 changed files with 5161 additions and 1734 deletions
+1 -1
View File
@@ -88,7 +88,7 @@ const DateInput = ({
<div
className={cn(
'input h-12 px-4 py-2 text-base font-normal leading-6 w-full rounded-lg! outline-none! transition-all duration-200 flex items-center',
'input h-12 px-4 py-2 text-base font-normal leading-6 w-full rounded outline-none! transition-all duration-200 flex items-center',
{
'border-error': isError,
'border-success!': isValid,
+1 -1
View File
@@ -70,7 +70,7 @@ const FileInput = ({
onBlur={onBlur}
disabled={disabled}
className={cn(
'grow file-input w-full h-12 rounded-lg!',
'grow file-input w-full h-12 rounded',
className?.input
)}
readOnly={readOnly}
+9 -9
View File
@@ -17,15 +17,15 @@ interface NumberInputProps extends Omit<TextInputProps, 'type'> {
}
const NumberInput = ({
thousandSeparator = ',',
decimalSeparator = '.',
decimalScale = 5,
allowNegative = true,
onChange,
inputPrefix,
inputSuffix,
...restProps
}: NumberInputProps) => {
thousandSeparator = ',',
decimalSeparator = '.',
decimalScale = 5,
allowNegative = true,
onChange,
inputPrefix,
inputSuffix,
...restProps
}: NumberInputProps) => {
const valueChangeHandler: OnValueChange = (
numberFormatValues,
sourceInfo
+52 -6
View File
@@ -1,6 +1,8 @@
'use client';
import { ComponentType, ReactNode, useEffect, useMemo, useState } from 'react';
import useSWR from 'swr';
import Select, {
OptionProps,
GroupBase,
@@ -11,7 +13,10 @@ import Select, {
import CreatableSelect from 'react-select/creatable';
import makeAnimated from 'react-select/animated';
import { useDebounce } from 'use-debounce';
import { cn } from '@/lib/helper';
import { cn, getByPath } from '@/lib/helper';
import { httpClientFetcher } from '@/services/http/client';
import { isResponseSuccess } from '@/lib/api-helper';
import { BaseApiResponse } from '@/types/api/api-general';
export interface OptionType {
value: string | number;
@@ -162,7 +167,7 @@ const SelectInput = <T extends OptionType>(props: SelectInputProps<T>) => {
classNames={{
control: ({ isFocused, isDisabled }) =>
cn(
'w-full min-h-12! rounded-lg! border bg-white transition-shadow cursor-pointer!',
'w-full min-h-12! rounded border bg-white transition-shadow cursor-pointer!',
{
'border-red-500! ring-2 ring-red-200': isError,
'border-indigo-500 ring-2 ring-indigo-200': isFocused,
@@ -178,16 +183,16 @@ const SelectInput = <T extends OptionType>(props: SelectInputProps<T>) => {
input: () => cn('text-gray-900'),
indicatorsContainer: () => cn('flex items-center gap-1 pr-2'),
dropdownIndicator: ({ isFocused }) =>
cn('p-1 rounded-md hover:bg-gray-100', {
cn('p-1 rounded hover:bg-gray-100', {
'text-gray-900': isFocused,
'text-gray-500': !isFocused,
'text-error!': isError,
}),
menu: () =>
cn('border border-gray-200 rounded-lg bg-white shadow-lg!'),
cn('border border-gray-200 rounded! bg-base-100 shadow-lg!'),
menuList: () => cn('p-2! max-h-60 overflow-auto'),
option: ({ isFocused, isSelected }) =>
cn('mt-1 px-3 py-2 rounded-md cursor-pointer!', {
cn('mt-1 px-3 py-2 rounded cursor-pointer!', {
'bg-indigo-600 text-white': isFocused,
'bg-blue-500!': isSelected,
'text-gray-700': !isFocused && !isSelected,
@@ -195,7 +200,7 @@ const SelectInput = <T extends OptionType>(props: SelectInputProps<T>) => {
multiValue: ({ getValue, index }) => {
const selectedValues = getValue() as T[];
return cn(
'bg-indigo-50 rounded-md py-0.5 pl-2 pr-1 flex items-center gap-1!',
'bg-indigo-50 rounded py-0.5 pl-2 pr-1 flex items-center gap-1!',
selectedValues[index]?.className
);
},
@@ -246,4 +251,45 @@ const SelectInput = <T extends OptionType>(props: SelectInputProps<T>) => {
);
};
const useSelect = <T,>(
basePath: string,
valueKey: keyof T,
labelKey: keyof T,
searchKey: string = 'search',
params?: { [key: string]: string }
) => {
const [inputValue, setInputValue] = useState('');
const optionsUrlParams = useMemo(() => {
return new URLSearchParams({
[searchKey]: inputValue ?? '',
...params,
}).toString();
}, [inputValue, searchKey]);
const optionsUrl = `${basePath}?${optionsUrlParams}`;
const { data, isLoading } = useSWR(optionsUrl, async (url) => {
return await httpClientFetcher<BaseApiResponse<T[]>>(url);
});
const options = isResponseSuccess(data)
? data.data.map((item) => {
return {
value: getByPath<T, number>(item, valueKey as string),
label: getByPath<T, string>(item, labelKey as string),
};
})
: [];
return {
inputValue,
setInputValue,
options,
isLoadingOptions: isLoading,
rawData: data,
};
};
export { useSelect };
export default SelectInput;
+1 -1
View File
@@ -83,7 +83,7 @@ const TextArea = ({
<textarea
className={cn(
'input h-auto px-4 py-2 text-base font-normal leading-6 w-full rounded-lg! outline-none! transition-all bg-white',
'input h-auto px-4 py-2 text-base font-normal leading-6 w-full rounded outline-none! transition-all bg-white',
{
'border-error': isError,
'border-success!': isValid,
+8 -4
View File
@@ -131,10 +131,14 @@ const TextInput = ({
onChange={onChange}
onBlur={onBlur}
disabled={disabled}
className={cn('grow bg-transparent outline-none', {
'cursor-not-allowed': disabled,
'text-gray-500': disabled,
}, className?.input)}
className={cn(
'grow bg-transparent outline-none',
{
'cursor-not-allowed': disabled,
'text-gray-500': disabled,
},
className?.input
)}
readOnly={readOnly}
/>