Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 62 additions & 4 deletions src/components/features/requests/DepositForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import { Modal } from '../../ui/Modal';
import { createInvestorRequest } from '../../../services/api';
import { useTranslation } from 'react-i18next';

const CASH_METHODS = ['CASH_ARS', 'CASH_USD'];

export const DepositForm = ({ userEmail }) => {
const { t } = useTranslation();
const [formData, setFormData] = useState({
amount: '',
method: 'CASH_ARS',
});
const [attachment, setAttachment] = useState(null);
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState(null);
const [modal, setModal] = useState(null);
Expand All @@ -25,13 +28,35 @@ export const DepositForm = ({ userEmail }) => {
{ value: 'CRYPTO', label: t('requests.method.crypto') },
];

const isCash = CASH_METHODS.includes(formData.method);
const attachmentRequired = !isCash;

const handleChange = (e) => {
setFormData({
...formData,
[e.target.name]: e.target.value,
});
};

const handleFileChange = (e) => {
const file = e.target.files?.[0] || null;
if (file && file.size > 5 * 1024 * 1024) {
setMessage({ type: 'error', text: t('deposits.requestForm.attachment.tooLarge') });
setAttachment(null);
return;
}
setAttachment(file);
setMessage(null);
};

const toBase64 = (file) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});

const handleSubmit = async (e) => {
e.preventDefault();

Expand All @@ -40,20 +65,31 @@ export const DepositForm = ({ userEmail }) => {
return;
}

if (attachmentRequired && !attachment) {
setMessage({ type: 'error', text: t('deposits.requestForm.validation.attachmentRequired') });
return;
}

setLoading(true);
setMessage(null);

const method = formData.method;
let attachmentUrl = null;
if (attachment) {
try {
attachmentUrl = await toBase64(attachment);
} catch {
attachmentUrl = null;
}
}

// Enviar solicitud al backend de Rails
const apiResult = await createInvestorRequest({
email: userEmail,
type: 'DEPOSIT',
amount: parseFloat(formData.amount),
method: method,
method: formData.method,
network: null,
transactionHash: null,
attachmentUrl: null,
attachmentUrl,
});

setLoading(false);
Expand All @@ -65,6 +101,7 @@ export const DepositForm = ({ userEmail }) => {
message: t('requests.registered.crypto'),
});
setFormData((s) => ({ ...s, amount: '' }));
setAttachment(null);
} else {
setMessage({
type: 'error',
Expand Down Expand Up @@ -120,6 +157,27 @@ export const DepositForm = ({ userEmail }) => {
</Select>
</div>

<div>
<label htmlFor="attachment" className="mb-2 block text-sm font-medium text-gray-700">
{t('deposits.requestForm.attachment.label')} {attachmentRequired ? '*' : ''}
</label>
<p className="mb-2 text-xs text-gray-500">
{t('deposits.requestForm.attachment.description')}
</p>
<input
id="attachment"
type="file"
accept="image/jpeg,image/png,image/webp"
onChange={handleFileChange}
className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-semibold file:bg-primary/10 file:text-primary hover:file:bg-primary/20 cursor-pointer"
/>
{attachment && (
<p className="mt-1 text-xs text-green-600">
{attachment.name} ({(attachment.size / 1024).toFixed(0)} KB)
</p>
)}
</div>

<div className="bg-accent/30 p-4 rounded-lg text-sm text-gray-700">
<p className="font-medium mb-1">{t('deposits.processingHoursTitle')}</p>
<p>• {t('deposits.processingHoursLine1')}</p>
Expand Down
9 changes: 7 additions & 2 deletions src/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,16 @@ const resources = {
placeholder: 'Ingresá el hash o ID',
},
attachment: {
label: 'Comprobante (opcional)',
label: 'Comprobante',
description: 'Adjuntá una captura del comprobante de pago (JPG, PNG o WEBP, máx 5MB)',
upload: 'Subir comprobante',
tooLarge: 'El archivo es demasiado grande. Máximo 5 MB.',
},
validation: {
invalidAmount: 'Ingresá un monto válido',
selectNetwork: 'Seleccioná una red',
attachmentRequired:
'El comprobante es obligatorio para depósitos que no sean en efectivo.',
},
submit: 'Enviar solicitud',
submitting: 'Enviando...',
Expand Down Expand Up @@ -393,13 +396,15 @@ const resources = {
placeholder: 'Enter hash or ID',
},
attachment: {
label: 'Receipt (optional)',
label: 'Receipt',
description: 'Attach a screenshot of the payment receipt (JPG, PNG or WEBP, max 5MB)',
upload: 'Upload receipt',
tooLarge: 'File is too large. Maximum 5 MB.',
},
validation: {
invalidAmount: 'Enter a valid amount',
selectNetwork: 'Select a network',
attachmentRequired: 'Receipt is required for non-cash deposits.',
},
submit: 'Send request',
submitting: 'Sending...',
Expand Down