File size: 5,249 Bytes
e9d5b7d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
"use client";
import { useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { TransferCoinsSchema, type TransferCoinsInput } from "@/lib/schemas";
import { transferCoins } from "@/lib/actions/user";
import { useToast } from "@/hooks/use-toast";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
DialogClose,
} from "@/components/ui/dialog";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
FormDescription,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Loader2, Send, Coins } from "lucide-react";
interface TransferCoinsDialogProps {
isOpen: boolean;
onOpenChange: (isOpen: boolean) => void;
currentUserCoins: number;
onTransferSuccess: (newBalance: number) => void;
}
export function TransferCoinsDialog({
isOpen,
onOpenChange,
currentUserCoins,
onTransferSuccess,
}: TransferCoinsDialogProps) {
const { toast } = useToast();
const [isLoading, setIsLoading] = useState(false);
const form = useForm<TransferCoinsInput>({
resolver: zodResolver(TransferCoinsSchema),
defaultValues: {
recipientEmail: "",
amount: 0,
},
});
async function onSubmit(values: TransferCoinsInput) {
setIsLoading(true);
try {
const result = await transferCoins(values);
toast({
title: result.success ? "Transfer Successful!" : "Transfer Failed",
description: result.message,
variant: result.success ? "default" : "destructive",
});
if (result.success && result.newSenderBalance !== undefined) {
onTransferSuccess(result.newSenderBalance);
form.reset();
onOpenChange(false); // Close dialog on success
}
} catch (error) {
toast({
title: "Error",
description: "An unexpected error occurred. Please try again.",
variant: "destructive",
});
} finally {
setIsLoading(false);
}
}
return (
<Dialog open={isOpen} onOpenChange={(open) => {
if (!isLoading) { // Prevent closing while submitting
onOpenChange(open);
if (!open) form.reset(); // Reset form if dialog is closed
}
}}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle className="flex items-center">
<Send className="mr-2 h-5 w-5 text-primary" />
Transfer Coins
</DialogTitle>
<DialogDescription>
Send coins to another user. Make sure the recipient's email is correct.
</DialogDescription>
</DialogHeader>
<div className="py-2">
<div className="flex items-center text-sm text-muted-foreground mb-4 p-2 bg-secondary/50 rounded-md">
<Coins className="mr-2 h-4 w-4 text-yellow-500" />
Your current balance:
<span className="font-semibold text-foreground ml-1">{currentUserCoins.toLocaleString()} Coins</span>
</div>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="recipientEmail"
render={({ field }) => (
<FormItem>
<FormLabel>Recipient's Email</FormLabel>
<FormControl>
<Input placeholder="recipient@example.com" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="amount"
render={({ field }) => (
<FormItem>
<FormLabel>Amount to Transfer</FormLabel>
<FormControl>
<Input
type="number"
placeholder="Enter amount"
{...field}
onChange={(e) => field.onChange(parseInt(e.target.value, 10) || 0)}
/>
</FormControl>
<FormDescription>
Enter a whole number of coins to transfer.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter className="pt-4">
<DialogClose asChild>
<Button type="button" variant="outline" disabled={isLoading}>
Cancel
</Button>
</DialogClose>
<Button type="submit" disabled={isLoading || form.getValues("amount") <=0}>
{isLoading ? (
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
) : (
<Send className="mr-2 h-4 w-4" />
)}
Send Coins
</Button>
</DialogFooter>
</form>
</Form>
</div>
</DialogContent>
</Dialog>
);
}
|