dstpabuaran.com/resources/js/components/rupiah-input.tsx
Yoga Pangestu a138ffe63c feat: add media library configuration and file upload components
- Added `media-library.php` configuration file for managing media uploads and conversions.
- Updated `filesystems.php` to set default visibility for AWS S3 storage.
- Implemented `FileUpload` component for handling file uploads with preview and error handling.
- Created `ImagePreviewModal` component for displaying image previews in a modal.
- Introduced `Attachment` UI components for better file attachment handling.
- Added `useFileUpload` hook to manage file upload state and logic.
- Implemented utility functions for uploading files to S3 with presigned URLs.
- Created API route for generating presigned URLs for file uploads.
2026-07-30 10:16:49 +07:00

83 lines
2.0 KiB
TypeScript

import { useCallback, useRef, useState } from 'react';
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
InputGroupText,
} from '@/components/ui/input-group';
type RupiahInputProps = {
name?: string;
defaultValue?: number;
placeholder?: string;
disabled?: boolean;
min?: number;
max?: number;
className?: string;
};
function formatRupiah(value: number): string {
return value.toLocaleString('id-ID');
}
function parseRupiah(value: string): number {
const cleaned = value.replace(/[^0-9]/g, '');
return cleaned === '' ? 0 : parseInt(cleaned, 10);
}
export function RupiahInput({
name,
defaultValue = 0,
placeholder = '0',
disabled = false,
min,
max,
className,
}: RupiahInputProps) {
const [displayValue, setDisplayValue] = useState(formatRupiah(defaultValue));
const lastValidRef = useRef(defaultValue);
const handleChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
const raw = parseRupiah(e.target.value);
let clamped = raw;
if (min !== undefined && raw < min) {
clamped = min;
}
if (max !== undefined && raw > max) {
clamped = max;
}
lastValidRef.current = clamped;
setDisplayValue(formatRupiah(clamped));
},
[min, max],
);
const handleBlur = useCallback(() => {
setDisplayValue(formatRupiah(lastValidRef.current));
}, []);
return (
<InputGroup className={className}>
<InputGroupAddon>
<InputGroupText>Rp</InputGroupText>
</InputGroupAddon>
<InputGroupInput
name={name}
type="text"
inputMode="numeric"
value={displayValue}
onChange={handleChange}
onBlur={handleBlur}
placeholder={placeholder}
disabled={disabled}
autoComplete="off"
/>
</InputGroup>
);
}