From 214c6e96eeb258608172518c2eb56cf393068220 Mon Sep 17 00:00:00 2001 From: Benjtalkshow Date: Fri, 20 Feb 2026 13:10:59 +0100 Subject: [PATCH 1/3] fix: resolve all lint issues and setup husky hooks --- .husky/pre-commit | 1 + .lintstagedrc | 4 + app/api/compliance/status/route.ts | 44 +- app/api/compliance/terms/route.ts | 56 +- app/api/compliance/upgrade/route.ts | 64 +- app/api/withdrawal/submit/route.ts | 44 +- components/compliance/appeal-dialog.tsx | 178 +++-- components/compliance/document-upload.tsx | 173 +++-- components/compliance/limits-display.tsx | 160 +++-- components/compliance/terms-dialog.tsx | 146 ++-- components/compliance/tier-upgrade-dialog.tsx | 295 ++++---- components/wallet/wallet-sheet.tsx | 1 - components/wallet/withdrawal-section.tsx | 475 +++++++------ lib/services/appeal.ts | 82 ++- lib/services/compliance.ts | 658 +++++++++--------- lib/services/geo-restriction.ts | 212 +++--- package-lock.json | 251 +++++-- package.json | 6 +- 18 files changed, 1616 insertions(+), 1234 deletions(-) create mode 100644 .husky/pre-commit create mode 100644 .lintstagedrc diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..db7dfc5 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npx lint-staged --concurrent false && npm run build diff --git a/.lintstagedrc b/.lintstagedrc new file mode 100644 index 0000000..681f620 --- /dev/null +++ b/.lintstagedrc @@ -0,0 +1,4 @@ +{ + "*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"], + "*.{json,md,css}": ["prettier --write"] +} diff --git a/app/api/compliance/status/route.ts b/app/api/compliance/status/route.ts index 9054ac5..35a9563 100644 --- a/app/api/compliance/status/route.ts +++ b/app/api/compliance/status/route.ts @@ -3,26 +3,30 @@ import { getCurrentUser } from "@/lib/server-auth"; import { ComplianceService } from "@/lib/services/compliance"; import { TermsService } from "@/lib/services/terms"; -export async function GET(request: NextRequest) { - try { - const user = await getCurrentUser(); - if (!user) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export async function GET(_request: NextRequest) { + try { + const user = await getCurrentUser(); + if (!user) { + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + } - const compliance = await ComplianceService.getUserCompliance(user.id); - const remaining = await ComplianceService.getRemainingLimits(user.id); - const termsStatus = await TermsService.getUserTermsStatus(user.id); - const nextTier = ComplianceService.getNextTier(compliance.currentTier); + const compliance = await ComplianceService.getUserCompliance(user.id); + const remaining = await ComplianceService.getRemainingLimits(user.id); + const termsStatus = await TermsService.getUserTermsStatus(user.id); + const nextTier = ComplianceService.getNextTier(compliance.currentTier); - return NextResponse.json({ - compliance, - remaining, - termsStatus, - nextTier, - }); - } catch (error) { - console.error("Error fetching compliance status:", error); - return NextResponse.json({ error: "Internal Server Error" }, { status: 500 }); - } + return NextResponse.json({ + compliance, + remaining, + termsStatus, + nextTier, + }); + } catch (error) { + console.error("Error fetching compliance status:", error); + return NextResponse.json( + { error: "Internal Server Error" }, + { status: 500 }, + ); + } } diff --git a/app/api/compliance/terms/route.ts b/app/api/compliance/terms/route.ts index 22ab0e5..3313be5 100644 --- a/app/api/compliance/terms/route.ts +++ b/app/api/compliance/terms/route.ts @@ -2,34 +2,42 @@ import { NextRequest, NextResponse } from "next/server"; import { getCurrentUser } from "@/lib/server-auth"; import { TermsService } from "@/lib/services/terms"; -export async function GET(request: NextRequest) { - try { - const terms = await TermsService.getCurrentTermsVersion(); - return NextResponse.json(terms); - } catch (error) { - return NextResponse.json({ error: "Failed to fetch terms" }, { status: 500 }); - } +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export async function GET(_request: NextRequest) { + try { + const terms = await TermsService.getCurrentTermsVersion(); + return NextResponse.json(terms); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (_error) { + return NextResponse.json( + { error: "Failed to fetch terms" }, + { status: 500 }, + ); + } } export async function POST(request: NextRequest) { - try { - const user = await getCurrentUser(); - if (!user) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } + try { + const user = await getCurrentUser(); + if (!user) { + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + } - const { termsVersionId } = await request.json(); - const ip = request.headers.get('x-forwarded-for') || '0.0.0.0'; - const userAgent = request.headers.get('user-agent') || 'unknown'; + const { termsVersionId } = await request.json(); + const ip = request.headers.get("x-forwarded-for") || "0.0.0.0"; + const userAgent = request.headers.get("user-agent") || "unknown"; - const acceptance = await TermsService.acceptTerms(user.id, termsVersionId, { - ipAddress: ip, - userAgent, - }); + const acceptance = await TermsService.acceptTerms(user.id, termsVersionId, { + ipAddress: ip, + userAgent, + }); - return NextResponse.json(acceptance); - } catch (error) { - console.error("Error accepting terms:", error); - return NextResponse.json({ error: "Failed to accept terms" }, { status: 500 }); - } + return NextResponse.json(acceptance); + } catch (error) { + console.error("Error accepting terms:", error); + return NextResponse.json( + { error: "Failed to accept terms" }, + { status: 500 }, + ); + } } diff --git a/app/api/compliance/upgrade/route.ts b/app/api/compliance/upgrade/route.ts index c54ad2e..f9bc36c 100644 --- a/app/api/compliance/upgrade/route.ts +++ b/app/api/compliance/upgrade/route.ts @@ -3,39 +3,45 @@ import { getCurrentUser } from "@/lib/server-auth"; import { VerificationService } from "@/lib/services/verification"; export async function POST(request: NextRequest) { - try { - const user = await getCurrentUser(); - if (!user) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } + try { + const user = await getCurrentUser(); + if (!user) { + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + } - const { targetTier } = await request.json(); + const { targetTier } = await request.json(); - const verificationRequest = await VerificationService.createVerificationRequest( - user.id, - targetTier - ); + const verificationRequest = + await VerificationService.createVerificationRequest(user.id, targetTier); - return NextResponse.json(verificationRequest); - } catch (error: any) { - console.error("Error creating verification request:", error); - return NextResponse.json( - { error: error.message || "Failed to create verification request" }, - { status: 400 } - ); - } + return NextResponse.json(verificationRequest); + } catch (error) { + console.error("Error creating verification request:", error); + return NextResponse.json( + { + error: + (error as Error).message || "Failed to create verification request", + }, + { status: 400 }, + ); + } } -export async function GET(request: NextRequest) { - try { - const user = await getCurrentUser(); - if (!user) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } - - const status = await VerificationService.getVerificationStatus(user.id); - return NextResponse.json(status); - } catch (error) { - return NextResponse.json({ error: "Failed to fetch verification status" }, { status: 500 }); +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export async function GET(_request: NextRequest) { + try { + const user = await getCurrentUser(); + if (!user) { + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } + + const status = await VerificationService.getVerificationStatus(user.id); + return NextResponse.json(status); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (_error) { + return NextResponse.json( + { error: "Failed to fetch verification status" }, + { status: 500 }, + ); + } } diff --git a/app/api/withdrawal/submit/route.ts b/app/api/withdrawal/submit/route.ts index ce43753..45a3935 100644 --- a/app/api/withdrawal/submit/route.ts +++ b/app/api/withdrawal/submit/route.ts @@ -3,29 +3,29 @@ import { getCurrentUser } from "@/lib/server-auth"; import { WithdrawalService } from "@/lib/services/withdrawal"; export async function POST(request: NextRequest) { - try { - const user = await getCurrentUser(); - if (!user) { - return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); - } + try { + const user = await getCurrentUser(); + if (!user) { + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + } - const { amount, currency, destinationId } = await request.json(); - const ip = request.headers.get('x-forwarded-for') || '0.0.0.0'; + const { amount, currency, destinationId } = await request.json(); + const ip = request.headers.get("x-forwarded-for") || "0.0.0.0"; - const withdrawal = await WithdrawalService.submit( - user.id, - amount, - currency, - destinationId, - ip - ); + const withdrawal = await WithdrawalService.submit( + user.id, + amount, + currency, + destinationId, + ip, + ); - return NextResponse.json(withdrawal); - } catch (error: any) { - console.error("Error submitting withdrawal:", error); - return NextResponse.json( - { error: error.message || "Withdrawal failed" }, - { status: 400 } - ); - } + return NextResponse.json(withdrawal); + } catch (error) { + console.error("Error submitting withdrawal:", error); + return NextResponse.json( + { error: (error as Error).message || "Withdrawal failed" }, + { status: 400 }, + ); + } } diff --git a/components/compliance/appeal-dialog.tsx b/components/compliance/appeal-dialog.tsx index 3cbbcd1..9da687b 100644 --- a/components/compliance/appeal-dialog.tsx +++ b/components/compliance/appeal-dialog.tsx @@ -1,96 +1,120 @@ "use client"; import { useState } from "react"; -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { AppealService } from "@/lib/services/appeal"; interface AppealDialogProps { - open: boolean; - onOpenChange: (open: boolean) => void; - verificationRequestId: string; - userId: string; - rejectionReason?: string; + open: boolean; + onOpenChange: (open: boolean) => void; + verificationRequestId: string; + userId: string; + rejectionReason?: string; } -export function AppealDialog({ open, onOpenChange, verificationRequestId, userId, rejectionReason }: AppealDialogProps) { - const [reason, setReason] = useState(""); - const [additionalInfo, setAdditionalInfo] = useState(""); - const [submitting, setSubmitting] = useState(false); +export function AppealDialog({ + open, + onOpenChange, + verificationRequestId, + userId, + rejectionReason, +}: AppealDialogProps) { + const [reason, setReason] = useState(""); + const [additionalInfo, setAdditionalInfo] = useState(""); + const [submitting, setSubmitting] = useState(false); - const handleSubmit = async () => { - if (!reason.trim()) return; + const handleSubmit = async () => { + if (!reason.trim()) return; - setSubmitting(true); - try { - await AppealService.submitAppeal(userId, verificationRequestId, reason, additionalInfo); - alert('Appeal submitted successfully. Our team will review it within 3-5 business days.'); - onOpenChange(false); - setReason(""); - setAdditionalInfo(""); - } catch (error: any) { - alert(error.message || 'Failed to submit appeal'); - } finally { - setSubmitting(false); - } - }; + setSubmitting(true); + try { + await AppealService.submitAppeal( + userId, + verificationRequestId, + reason, + additionalInfo, + ); + alert( + "Appeal submitted successfully. Our team will review it within 3-5 business days.", + ); + onOpenChange(false); + setReason(""); + setAdditionalInfo(""); + } catch (error) { + alert((error as Error).message || "Failed to submit appeal"); + } finally { + setSubmitting(false); + } + }; - return ( - - - - Appeal Verification Decision - - Explain why you believe the rejection should be reconsidered. - - + return ( + + + + Appeal Verification Decision + + Explain why you believe the rejection should be reconsidered. + + -
- {rejectionReason && ( -
-

Original Rejection Reason:

-

{rejectionReason}

-
- )} +
+ {rejectionReason && ( +
+

+ Original Rejection Reason: +

+

{rejectionReason}

+
+ )} -
- -