|
1 | 1 | "use client"; |
2 | 2 |
|
3 | | -import { useState, memo, useMemo } from 'react'; |
| 3 | +import { useState, memo, useMemo, useEffect } from 'react'; |
| 4 | +import { useForm } from 'react-hook-form'; |
| 5 | +import { zodResolver } from '@hookform/resolvers/zod'; |
| 6 | +import { editPaymentLinkSchema, type EditPaymentLinkFormValues } from '@/lib/utils/validation'; |
4 | 7 | import { Card, CardContent, CardHeader, CardTitle, CardDescription, Button, Input, Label } from '@/components/ui'; |
5 | 8 | import { CopyAddress, EmptyState, ErrorDisplay } from '@/components/shared'; |
6 | 9 | import { PageHeader } from '@/components/shared/PageHeader'; |
@@ -166,8 +169,24 @@ export default function PaymentsPage() { |
166 | 169 | resetForm(); |
167 | 170 | }; |
168 | 171 |
|
169 | | - const handleEditSubmit = (e: React.FormEvent) => { |
170 | | - e.preventDefault(); |
| 172 | + const { register: registerEdit, handleSubmit: handleEditSubmitForm, reset: resetEditForm, formState: { errors: editErrors } } = useForm<EditPaymentLinkFormValues>({ |
| 173 | + resolver: zodResolver(editPaymentLinkSchema), |
| 174 | + }); |
| 175 | + |
| 176 | + useEffect(() => { |
| 177 | + if (editingLink) { |
| 178 | + resetEditForm({ |
| 179 | + label: editingLink.source ?? '', |
| 180 | + amount: editingLink.amountUsdc ? String(editingLink.amountUsdc) : '', |
| 181 | + currency: editingLink.amountUsdc ? 'USDC' : 'XLM', |
| 182 | + expiry: '', |
| 183 | + redirectUrl: '', |
| 184 | + reference: '', |
| 185 | + }); |
| 186 | + } |
| 187 | + }, [editingLink, resetEditForm]); |
| 188 | + |
| 189 | + const handleEditSubmit = (data: EditPaymentLinkFormValues) => { |
171 | 190 | notifySuccess('Payment link updated successfully'); |
172 | 191 | setEditingLink(null); |
173 | 192 | }; |
@@ -471,21 +490,86 @@ export default function PaymentsPage() { |
471 | 490 |
|
472 | 491 | {/* Edit Dialog */} |
473 | 492 | <Dialog open={!!editingLink} onOpenChange={(open) => !open && setEditingLink(null)}> |
474 | | - <DialogContent className="sm:max-w-[425px] bg-card border-border/50"> |
| 493 | + <DialogContent className="sm:max-w-[425px] bg-card border-border/50 max-h-[85dvh] overflow-y-auto"> |
475 | 494 | <DialogHeader> |
476 | 495 | <DialogTitle>Edit Payment Link</DialogTitle> |
477 | 496 | <DialogDescription>Update details for {editingLink?.source}</DialogDescription> |
478 | 497 | </DialogHeader> |
479 | | - <form onSubmit={handleEditSubmit} className="space-y-4 py-2"> |
| 498 | + <form onSubmit={handleEditSubmitForm(handleEditSubmit)} className="space-y-4 py-2"> |
480 | 499 | <div className="space-y-2"> |
481 | 500 | <Label htmlFor="edit-title">Title / Label</Label> |
482 | | - <Input id="edit-title" defaultValue={editingLink?.source ?? ''} /> |
| 501 | + <Input |
| 502 | + id="edit-title" |
| 503 | + className="bg-background/50 border-border/50" |
| 504 | + {...registerEdit('label')} |
| 505 | + /> |
| 506 | + {editErrors.label && ( |
| 507 | + <p className="text-xs text-destructive mt-1">{editErrors.label.message}</p> |
| 508 | + )} |
| 509 | + </div> |
| 510 | + |
| 511 | + <div className="grid grid-cols-2 gap-3"> |
| 512 | + <div className="space-y-2"> |
| 513 | + <Label htmlFor="edit-amount">Amount (Optional)</Label> |
| 514 | + <Input |
| 515 | + id="edit-amount" |
| 516 | + type="number" |
| 517 | + placeholder="0.00" |
| 518 | + className="bg-background/50 border-border/50" |
| 519 | + {...registerEdit('amount')} |
| 520 | + /> |
| 521 | + {editErrors.amount && ( |
| 522 | + <p className="text-xs text-destructive mt-1">{editErrors.amount.message}</p> |
| 523 | + )} |
| 524 | + </div> |
| 525 | + <div className="space-y-2"> |
| 526 | + <Label htmlFor="edit-currency">Currency</Label> |
| 527 | + <select |
| 528 | + id="edit-currency" |
| 529 | + className="flex h-10 w-full rounded-md border border-input border-border/50 bg-background/50 px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50" |
| 530 | + {...registerEdit('currency')} |
| 531 | + > |
| 532 | + <option value="USDC">USDC</option> |
| 533 | + <option value="XLM">XLM</option> |
| 534 | + <option value="USDT">USDT</option> |
| 535 | + </select> |
| 536 | + </div> |
| 537 | + </div> |
| 538 | + |
| 539 | + <div className="space-y-2"> |
| 540 | + <Label htmlFor="edit-reference">Internal Reference</Label> |
| 541 | + <Input |
| 542 | + id="edit-reference" |
| 543 | + placeholder="e.g. INV-2026-001" |
| 544 | + className="bg-background/50 border-border/50" |
| 545 | + {...registerEdit('reference')} |
| 546 | + /> |
| 547 | + </div> |
| 548 | + |
| 549 | + <div className="space-y-2"> |
| 550 | + <Label htmlFor="edit-expiry">Expiry Date</Label> |
| 551 | + <Input |
| 552 | + id="edit-expiry" |
| 553 | + type="date" |
| 554 | + className="bg-background/50 border-border/50" |
| 555 | + {...registerEdit('expiry')} |
| 556 | + /> |
483 | 557 | </div> |
| 558 | + |
484 | 559 | <div className="space-y-2"> |
485 | | - <Label htmlFor="edit-amount">Amount (USDC)</Label> |
486 | | - <Input id="edit-amount" type="number" defaultValue={editingLink?.amountUsdc ?? 0} /> |
| 560 | + <Label htmlFor="edit-redirect">Redirect URL (On success)</Label> |
| 561 | + <Input |
| 562 | + id="edit-redirect" |
| 563 | + placeholder="https://yourstore.com/thank-you" |
| 564 | + className="bg-background/50 border-border/50" |
| 565 | + {...registerEdit('redirectUrl')} |
| 566 | + /> |
| 567 | + {editErrors.redirectUrl && ( |
| 568 | + <p className="text-xs text-destructive mt-1">{editErrors.redirectUrl.message}</p> |
| 569 | + )} |
487 | 570 | </div> |
488 | | - <DialogFooter> |
| 571 | + |
| 572 | + <DialogFooter className="pt-4"> |
489 | 573 | <Button type="button" variant="ghost" onClick={() => setEditingLink(null)}>Cancel</Button> |
490 | 574 | <Button type="submit">Save Changes</Button> |
491 | 575 | </DialogFooter> |
|
0 commit comments