Implement Quick Actions functionality on Financials page (Monthly Report Download, Tax Settings)

This commit is contained in:
CycroftX
2026-02-03 20:58:38 +05:30
parent 8b8cab9385
commit 248e26d880
2 changed files with 222 additions and 4 deletions

View File

@@ -0,0 +1,172 @@
import { useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import { Loader2, Landmark } from "lucide-react";
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
} from "@/components/ui/sheet";
import { Button } from "@/components/ui/button";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { toast } from "sonner";
const taxSettingsSchema = z.object({
gstNumber: z.string().min(15, "GST Number must be 15 characters").max(15, "GST Number must be 15 characters"),
panNumber: z.string().min(10, "PAN Number must be 10 characters").max(10, "PAN Number must be 10 characters"),
platformFeePercentage: z.string().regex(/^\d+(\.\d{1,2})?$/, "Must be a valid percentage"),
taxPercentage: z.string().regex(/^\d+(\.\d{1,2})?$/, "Must be a valid percentage"),
});
type FormValues = z.infer<typeof taxSettingsSchema>;
interface TaxSettingsSheetProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}
export function TaxSettingsSheet({ open, onOpenChange }: TaxSettingsSheetProps) {
const [isSubmitting, setIsSubmitting] = useState(false);
const form = useForm<FormValues>({
resolver: zodResolver(taxSettingsSchema),
defaultValues: {
gstNumber: "27AAAAA0000A1Z5",
panNumber: "AAAAA0000A",
platformFeePercentage: "12",
taxPercentage: "18",
},
});
async function onSubmit(data: FormValues) {
setIsSubmitting(true);
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 1500));
console.log("Tax settings updated:", data);
toast.success("Tax settings updated successfully");
setIsSubmitting(false);
onOpenChange(false);
}
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent className="w-[400px] sm:w-[540px]">
<SheetHeader>
<SheetTitle>Tax & Platform Settings</SheetTitle>
<SheetDescription>
Configure platform fees and tax details.
</SheetDescription>
</SheetHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6 mt-6">
<div className="bg-secondary/20 p-4 rounded-lg flex items-start gap-4 mb-6">
<Landmark className="h-6 w-6 text-primary mt-1" />
<div>
<h4 className="font-semibold text-foreground">Global Settings</h4>
<p className="text-sm text-muted-foreground">These settings apply to all new events and transactions by default.</p>
</div>
</div>
<FormField
control={form.control}
name="platformFeePercentage"
render={({ field }) => (
<FormItem>
<FormLabel>Default Platform Fee (%)</FormLabel>
<FormControl>
<Input placeholder="12" {...field} />
</FormControl>
<FormDescription>
Percentage of ticket sales taken as platform revenue.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="taxPercentage"
render={({ field }) => (
<FormItem>
<FormLabel>Govt. Tax (GST) (%)</FormLabel>
<FormControl>
<Input placeholder="18" {...field} />
</FormControl>
<FormDescription>
Applicable GST on platform fees.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<div className="grid grid-cols-2 gap-4">
<FormField
control={form.control}
name="gstNumber"
render={({ field }) => (
<FormItem>
<FormLabel>Company GSTIN</FormLabel>
<FormControl>
<Input placeholder="27AAAAA0000A1Z5" {...field} className="uppercase" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="panNumber"
render={({ field }) => (
<FormItem>
<FormLabel>Company PAN</FormLabel>
<FormControl>
<Input placeholder="AAAAA0000A" {...field} className="uppercase" />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="flex justify-end gap-3 pt-4">
<Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
Cancel
</Button>
<Button type="submit" disabled={isSubmitting} className="bg-primary text-primary-foreground">
{isSubmitting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Updating...
</>
) : (
"Save Changes"
)}
</Button>
</div>
</form>
</Form>
</SheetContent>
</Sheet>
);
}

View File

@@ -1,16 +1,54 @@
import { IndianRupee, TrendingUp, Wallet } from 'lucide-react'; import { useState } from 'react';
import { IndianRupee, TrendingUp, Wallet, Download } from 'lucide-react';
import { AppLayout } from '@/components/layout/AppLayout'; import { AppLayout } from '@/components/layout/AppLayout';
import { formatCurrency, mockRevenueData } from '@/data/mockData'; import { formatCurrency, mockRevenueData } from '@/data/mockData';
import { mockTransactions } from '@/data/mockFinancialData';
import { SettlementTable } from '@/features/financials/components/SettlementTable'; import { SettlementTable } from '@/features/financials/components/SettlementTable';
import { TransactionList } from '@/features/financials/components/TransactionList'; import { TransactionList } from '@/features/financials/components/TransactionList';
import { TaxSettingsSheet } from '@/features/financials/components/TaxSettingsSheet';
import { toast } from 'sonner';
export default function Financials() { export default function Financials() {
const [showTaxSettings, setShowTaxSettings] = useState(false);
const totalRevenue = mockRevenueData.reduce((sum, d) => sum + d.revenue, 0); const totalRevenue = mockRevenueData.reduce((sum, d) => sum + d.revenue, 0);
const totalPayouts = mockRevenueData.reduce((sum, d) => sum + d.payouts, 0); const totalPayouts = mockRevenueData.reduce((sum, d) => sum + d.payouts, 0);
// Calculating platform fee (approx 10% of revenue for mock) // Calculating platform fee (approx 10% of revenue for mock)
const platformEarnings = totalRevenue * 0.12; const platformEarnings = totalRevenue * 0.12;
const handleDownloadReport = () => {
try {
const headers = ['ID', 'Date', 'Type', 'Title', 'Partner', 'Amount', 'Status'];
const csvContent = [
headers.join(','),
...mockTransactions.map(tx => [
tx.id,
new Date(tx.date).toLocaleDateString(),
tx.type,
`"${tx.title}"`,
`"${tx.partner}"`,
tx.amount,
tx.status
].join(','))
].join('\n');
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', 'financial_report.csv');
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
toast.success("Monthly report downloaded successfully");
} catch (error) {
toast.error("Failed to generate report");
}
};
return ( return (
<AppLayout <AppLayout
title="Financials & Settlements" title="Financials & Settlements"
@@ -73,11 +111,17 @@ export default function Financials() {
<div className="neu-card p-6"> <div className="neu-card p-6">
<h3 className="font-semibold mb-4">Quick Actions</h3> <h3 className="font-semibold mb-4">Quick Actions</h3>
<div className="space-y-2"> <div className="space-y-2">
<button className="w-full text-left px-4 py-3 rounded-lg bg-secondary/50 hover:bg-secondary transition-colors text-sm font-medium flex items-center justify-between group"> <button
onClick={handleDownloadReport}
className="w-full text-left px-4 py-3 rounded-lg bg-secondary/50 hover:bg-secondary transition-colors text-sm font-medium flex items-center justify-between group"
>
Download Monthly Report Download Monthly Report
<IndianRupee className="h-4 w-4 text-muted-foreground group-hover:text-foreground" /> <Download className="h-4 w-4 text-muted-foreground group-hover:text-foreground" />
</button> </button>
<button className="w-full text-left px-4 py-3 rounded-lg bg-secondary/50 hover:bg-secondary transition-colors text-sm font-medium flex items-center justify-between group"> <button
onClick={() => setShowTaxSettings(true)}
className="w-full text-left px-4 py-3 rounded-lg bg-secondary/50 hover:bg-secondary transition-colors text-sm font-medium flex items-center justify-between group"
>
Update Tax Settings Update Tax Settings
<Wallet className="h-4 w-4 text-muted-foreground group-hover:text-foreground" /> <Wallet className="h-4 w-4 text-muted-foreground group-hover:text-foreground" />
</button> </button>
@@ -85,6 +129,8 @@ export default function Financials() {
</div> </div>
</div> </div>
</div> </div>
<TaxSettingsSheet open={showTaxSettings} onOpenChange={setShowTaxSettings} />
</AppLayout> </AppLayout>
); );
} }