89 lines
2.0 KiB
TypeScript
89 lines
2.0 KiB
TypeScript
import React from 'react';
|
|
import { IonInput, IonLabel } from '@ionic/react';
|
|
import { sanitizeMoneyInput, getCurrencySymbol } from '../utils/money';
|
|
import { useAuth } from '../contexts/AuthContext';
|
|
|
|
interface MoneyInputProps {
|
|
value: string;
|
|
onValueChange: (value: string) => void;
|
|
label?: string;
|
|
placeholder?: string;
|
|
error?: string;
|
|
}
|
|
|
|
const MoneyInput: React.FC<MoneyInputProps> = ({
|
|
value,
|
|
onValueChange,
|
|
label,
|
|
placeholder = '0.00',
|
|
error,
|
|
}) => {
|
|
const { profile } = useAuth();
|
|
const symbol = getCurrencySymbol(profile?.currency || 'USD');
|
|
|
|
const handleChange = (e: CustomEvent) => {
|
|
const rawValue = e.detail.value || '';
|
|
const sanitized = sanitizeMoneyInput(rawValue);
|
|
onValueChange(sanitized);
|
|
};
|
|
|
|
return (
|
|
<div className="money-input-container">
|
|
{label && (
|
|
<IonLabel
|
|
position="stacked"
|
|
className="semibold"
|
|
style={{ marginBottom: '8px', display: 'block', fontSize: '13px' }}
|
|
>
|
|
{label}
|
|
</IonLabel>
|
|
)}
|
|
<div
|
|
className="input-wrapper"
|
|
style={{
|
|
border: error ? '1px solid var(--ion-color-danger)' : 'none',
|
|
}}
|
|
>
|
|
<span
|
|
className="bold"
|
|
style={{
|
|
marginRight: '8px',
|
|
color: 'var(--color-text-primary)',
|
|
fontSize: '18px',
|
|
}}
|
|
>
|
|
{symbol}
|
|
</span>
|
|
<IonInput
|
|
type="text"
|
|
inputMode="decimal"
|
|
value={value}
|
|
placeholder={placeholder}
|
|
onIonChange={handleChange}
|
|
style={{
|
|
fontSize: '20px',
|
|
fontWeight: '700',
|
|
'--padding-top': '0',
|
|
'--padding-bottom': '0',
|
|
}}
|
|
className="tabular"
|
|
/>
|
|
</div>
|
|
{error && (
|
|
<IonLabel
|
|
color="danger"
|
|
style={{
|
|
fontSize: '12px',
|
|
marginTop: '4px',
|
|
display: 'block',
|
|
}}
|
|
>
|
|
{error}
|
|
</IonLabel>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default MoneyInput;
|