Files
gridpilot.gg/apps/website/client-wrapper/SponsorshipRequestsClient.tsx
2026-01-19 18:34:01 +01:00

77 lines
2.6 KiB
TypeScript

'use client';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Icon } from '@/ui/Icon';
import { ProgressLine } from '@/components/shared/ProgressLine';
import { ShieldAlert } from 'lucide-react';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { ClientWrapperProps } from '@/lib/contracts/components/ComponentContracts';
import type { Result } from '@/lib/contracts/Result';
import type { SponsorshipRequestsViewData } from '@/lib/view-data/SponsorshipRequestsViewData';
import { SponsorshipRequestsTemplate } from '@/templates/SponsorshipRequestsTemplate';
interface SponsorshipRequestsClientProps extends ClientWrapperProps<SponsorshipRequestsViewData> {
onAccept: (requestId: string) => Promise<Result<void, string>>;
onReject: (requestId: string, reason?: string) => Promise<Result<void, string>>;
}
export function SponsorshipRequestsClient({ viewData, onAccept, onReject }: SponsorshipRequestsClientProps) {
const router = useRouter();
const [isProcessing, setIsProcessing] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
const handleAccept = async (requestId: string) => {
setIsProcessing(requestId);
setError(null);
const result = await onAccept(requestId);
if (result.isErr()) {
setError(result.getError());
setIsProcessing(null);
} else {
router.refresh();
setIsProcessing(null);
}
};
const handleReject = async (requestId: string, reason?: string) => {
setIsProcessing(requestId);
setError(null);
const result = await onReject(requestId, reason);
if (result.isErr()) {
setError(result.getError());
setIsProcessing(null);
} else {
router.refresh();
setIsProcessing(null);
}
};
return (
<>
<ProgressLine isLoading={!!isProcessing} />
{error && (
<Box position="fixed" top={4} right={4} zIndex={50} maxWidth="md">
<Box bg="bg-error-red/10" p={4} rounded="md" border borderColor="border-error-red/20">
<Stack direction="row" align="center" gap={3}>
<Icon icon={ShieldAlert} size={5} color="text-error-red" />
<Box>
<Text weight="bold" color="text-error-red">Action Failed</Text>
<Text size="sm" color="text-error-red/80">{error}</Text>
</Box>
</Stack>
</Box>
</Box>
)}
<SponsorshipRequestsTemplate
viewData={viewData}
onAccept={handleAccept}
onReject={handleReject}
processingId={isProcessing}
/>
</>
);
}