Adds the full Next.js app (app/, components/, lib/, scripts/, assets/, docs/, Dockerfile, compose, configs) to version control. Security: - CIPC BizPortal customer-code logins (Login 1 + Login 3) now read CIPC_LOGIN1_CODE / CIPC_LOGIN1_PASSWORD / CIPC_LOGIN3_CODE / CIPC_LOGIN3_PASSWORD from .env.local instead of source. - BizPortal personal login in apply-bizportal route reads BIZPORTAL_ID_NO / BIZPORTAL_PASSWORD. - Added .env.example as the committed template. .gitignore excludes .env*, node_modules, .next, logs, sqlite, Playwright storage_state.json (live CIPC cookies), scratch dirs, client PDFs and debug screenshots.
489 lines
22 KiB
TypeScript
489 lines
22 KiB
TypeScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
|
|
interface AnnualReturn {
|
|
id: string;
|
|
ar_year: number;
|
|
ar_month: string;
|
|
is_filed: boolean;
|
|
date_filed: string;
|
|
amount_paid: number;
|
|
ar_non_compliance_date: string;
|
|
source: string;
|
|
}
|
|
|
|
interface TaxReturn {
|
|
id: string;
|
|
company: string;
|
|
return_type: "IRP6" | "IncomeTax";
|
|
period: string;
|
|
date_filed: string;
|
|
amount_paid: number;
|
|
}
|
|
|
|
interface Props {
|
|
companyId: string;
|
|
companyName: string;
|
|
initialRecords: AnnualReturn[];
|
|
irp6Records: TaxReturn[];
|
|
incomeTaxRecords: TaxReturn[];
|
|
}
|
|
|
|
const MONTH_ORDER = [
|
|
"JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
|
|
"JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER",
|
|
];
|
|
|
|
function sortRecords(records: AnnualReturn[]) {
|
|
return [...records].sort((a, b) => {
|
|
if (b.ar_year !== a.ar_year) return b.ar_year - a.ar_year;
|
|
return MONTH_ORDER.indexOf(a.ar_month) - MONTH_ORDER.indexOf(b.ar_month);
|
|
});
|
|
}
|
|
|
|
function filedBadge(filed: boolean) {
|
|
return filed ? (
|
|
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-semibold bg-emerald-500/10 text-emerald-400 border border-emerald-500/20">
|
|
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" className="flex-shrink-0">
|
|
<path d="M2 5l2.5 2.5L8 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
</svg>
|
|
Filed
|
|
</span>
|
|
) : (
|
|
<span className="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-semibold bg-amber-500/10 text-amber-400 border border-amber-500/20">
|
|
Outstanding
|
|
</span>
|
|
);
|
|
}
|
|
|
|
function formatAmount(amount: number) {
|
|
const abs = Math.abs(amount);
|
|
return abs > 0 ? `R ${abs.toLocaleString()}` : "—";
|
|
}
|
|
|
|
function formatDate(dateStr: string) {
|
|
if (!dateStr) return "—";
|
|
const d = new Date(dateStr + "T00:00:00");
|
|
return d.toLocaleDateString("en-ZA", { year: "numeric", month: "short", day: "numeric" });
|
|
}
|
|
|
|
function getNextSubmissionDate(latestYear: number | undefined) {
|
|
if (latestYear) {
|
|
const dueYear = latestYear + 1;
|
|
return `31 January ${dueYear}`;
|
|
}
|
|
const now = new Date();
|
|
return `31 January ${now.getFullYear()}`;
|
|
}
|
|
|
|
// ── SARS Returns Section ────────────────────────────────────────────────────────
|
|
|
|
function formatPeriod(period: string, returnType: string) {
|
|
if (returnType === "IRP6") {
|
|
if (period.length === 6) {
|
|
const year = period.slice(0, 4);
|
|
const num = period.slice(4);
|
|
return `${num === "1" ? "1st" : "2nd"} period ${year}`;
|
|
}
|
|
return period;
|
|
}
|
|
return period; // Income Tax: just the year
|
|
}
|
|
|
|
function SARSReturnsSection({ irp6Records, incomeTaxRecords }: { irp6Records: TaxReturn[]; incomeTaxRecords: TaxReturn[] }) {
|
|
if (irp6Records.length === 0 && incomeTaxRecords.length === 0) {
|
|
return (
|
|
<div className="flex flex-col items-center justify-center text-center gap-3 py-6">
|
|
<div className="w-10 h-10 rounded-full bg-surface-warm border border-border flex items-center justify-center">
|
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none">
|
|
<circle cx="9" cy="9" r="7" stroke="#475569" strokeWidth="1.5" />
|
|
<path d="M9 5.5v4M9 12h.01" stroke="#475569" strokeWidth="1.5" strokeLinecap="round" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-semibold text-fg">No filings recorded yet</p>
|
|
<p className="text-xs text-muted mt-1">Click "Record New Filing" to add an IRP6 or Income Tax submission.</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const latestIRP6 = [...irp6Records].sort((a, b) => b.period.localeCompare(a.period))[0];
|
|
const latestIncomeTax = [...incomeTaxRecords].sort((a, b) => b.period.localeCompare(a.period))[0];
|
|
|
|
return (
|
|
<div className="flex flex-col gap-5">
|
|
{/* IRP6 */}
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-2">
|
|
<span className="text-xs font-bold uppercase tracking-widest text-indigo-400">IRP6 — Provisional Tax</span>
|
|
{latestIRP6 && (
|
|
<span className="text-xs text-muted">· Latest: {formatPeriod(latestIRP6.period, "IRP6")}</span>
|
|
)}
|
|
</div>
|
|
<div className="overflow-hidden rounded-md border border-border">
|
|
<table className="w-full text-sm">
|
|
<thead>
|
|
<tr className="bg-border-soft border-b border-border">
|
|
<th className="text-left px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Period</th>
|
|
<th className="text-left px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Date Filed</th>
|
|
<th className="text-right px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-border">
|
|
{irp6Records.slice(0, 5).map((ret) => (
|
|
<tr key={ret.id} className="hover:bg-surface-warm/50 transition-colors">
|
|
<td className="px-4 py-3 font-mono font-semibold text-fg">{formatPeriod(ret.period, "IRP6")}</td>
|
|
<td className="px-4 py-3 font-mono text-muted text-xs">{formatDate(ret.date_filed)}</td>
|
|
<td className="px-4 py-3 text-right font-mono text-fg font-semibold">{formatAmount(ret.amount_paid)}</td>
|
|
</tr>
|
|
))}
|
|
{irp6Records.length === 0 && (
|
|
<tr>
|
|
<td colSpan={3} className="px-4 py-4 text-center text-sm text-muted">No IRP6 filings.</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Income Tax */}
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-2">
|
|
<span className="text-xs font-bold uppercase tracking-widest text-indigo-400">Income Tax</span>
|
|
{latestIncomeTax && (
|
|
<span className="text-xs text-muted">· Latest: {latestIncomeTax.period} year of assessment</span>
|
|
)}
|
|
</div>
|
|
<div className="overflow-hidden rounded-md border border-border">
|
|
<table className="w-full text-sm">
|
|
<thead>
|
|
<tr className="bg-border-soft border-b border-border">
|
|
<th className="text-left px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Year</th>
|
|
<th className="text-left px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Date Filed</th>
|
|
<th className="text-right px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Amount</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-border">
|
|
{incomeTaxRecords.slice(0, 5).map((ret) => (
|
|
<tr key={ret.id} className="hover:bg-surface-warm/50 transition-colors">
|
|
<td className="px-4 py-3 font-mono font-semibold text-fg">{ret.period}</td>
|
|
<td className="px-4 py-3 font-mono text-muted text-xs">{formatDate(ret.date_filed)}</td>
|
|
<td className="px-4 py-3 text-right font-mono text-fg font-semibold">{formatAmount(ret.amount_paid)}</td>
|
|
</tr>
|
|
))}
|
|
{incomeTaxRecords.length === 0 && (
|
|
<tr>
|
|
<td colSpan={3} className="px-4 py-4 text-center text-sm text-muted">No Income Tax filings.</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// ── New Filing Modal ──────────────────────────────────────────────────────────
|
|
|
|
function NewFilingModal({ companyId, onClose, onSuccess }: { companyId: string; onClose: () => void; onSuccess: () => void }) {
|
|
const [returnType, setReturnType] = useState<"IRP6" | "IncomeTax">("IRP6");
|
|
const [period, setPeriod] = useState("");
|
|
const [dateFiled, setDateFiled] = useState("");
|
|
const [amountPaid, setAmountPaid] = useState("");
|
|
const [saving, setSaving] = useState(false);
|
|
const [error, setError] = useState("");
|
|
|
|
function handleSubmit(e: React.FormEvent) {
|
|
e.preventDefault();
|
|
if (!period.trim() || !dateFiled) {
|
|
setError("Period and date filed are required.");
|
|
return;
|
|
}
|
|
setSaving(true);
|
|
setError("");
|
|
|
|
const fields: Record<string, unknown> = {
|
|
company: companyId,
|
|
return_type: returnType,
|
|
period: period.trim(),
|
|
date_filed: dateFiled,
|
|
amount_paid: amountPaid ? parseFloat(amountPaid) : 0,
|
|
};
|
|
|
|
fetch("/api/pb/records/create", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ collection: "ysterbaard_sars_irp6_income_tax", fields }),
|
|
})
|
|
.then((r) => r.json())
|
|
.then((data) => {
|
|
if (data.error) throw new Error(data.error);
|
|
onSuccess();
|
|
})
|
|
.catch((err: Error) => {
|
|
setError(err.message || "Failed to save. Please try again.");
|
|
setSaving(false);
|
|
});
|
|
}
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm" onClick={(e) => e.target === e.currentTarget && onClose()}>
|
|
<div className="bg-surface border border-border rounded-xl shadow-2xl w-full max-w-md mx-4">
|
|
<div className="flex items-center justify-between px-6 py-4 border-b border-border">
|
|
<h3 className="text-lg font-semibold text-fg">Record SARS Filing</h3>
|
|
<button onClick={onClose} className="text-muted hover:text-fg transition-colors">
|
|
<svg width="18" height="18" viewBox="0 0 18 18" fill="none">
|
|
<path d="M4 4l10 10M14 4L4 14" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<form onSubmit={handleSubmit} className="p-6 flex flex-col gap-5">
|
|
{/* Return type */}
|
|
<div>
|
|
<label className="block text-xs font-semibold text-muted uppercase tracking-wider mb-2">Return Type</label>
|
|
<div className="grid grid-cols-2 gap-2">
|
|
{(["IRP6", "IncomeTax"] as const).map((t) => (
|
|
<button
|
|
key={t}
|
|
type="button"
|
|
onClick={() => setReturnType(t)}
|
|
className={`px-4 py-2.5 rounded-md border text-sm font-semibold transition-colors ${
|
|
returnType === t
|
|
? "bg-indigo-600 border-indigo-500 text-white"
|
|
: "bg-surface-warm border-border text-fg hover:border-indigo-400"
|
|
}`}
|
|
>
|
|
{t === "IRP6" ? "IRP6 — Provisional Tax" : "Income Tax"}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Period */}
|
|
<div>
|
|
<label className="block text-xs font-semibold text-muted uppercase tracking-wider mb-2">
|
|
Period <span className="text-red-400">*</span>
|
|
</label>
|
|
<input
|
|
type="text"
|
|
value={period}
|
|
onChange={(e) => setPeriod(e.target.value)}
|
|
placeholder={returnType === "IRP6" ? "e.g. 202602" : "e.g. 2023"}
|
|
className="w-full px-4 py-2.5 rounded-md border border-border bg-background text-fg text-sm placeholder-muted focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
|
|
required
|
|
/>
|
|
<p className="text-xs text-muted mt-1">
|
|
{returnType === "IRP6" ? "Year + 1 or 2 (e.g. 202602 = 2nd period 2026)" : "Year of assessment (e.g. 2023)"}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Date filed */}
|
|
<div>
|
|
<label className="block text-xs font-semibold text-muted uppercase tracking-wider mb-2">
|
|
Date Filed <span className="text-red-400">*</span>
|
|
</label>
|
|
<input
|
|
type="date"
|
|
value={dateFiled}
|
|
onChange={(e) => setDateFiled(e.target.value)}
|
|
className="w-full px-4 py-2.5 rounded-md border border-border bg-background text-fg text-sm focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
{/* Amount paid */}
|
|
<div>
|
|
<label className="block text-xs font-semibold text-muted uppercase tracking-wider mb-2">Amount Paid (R)</label>
|
|
<input
|
|
type="number"
|
|
value={amountPaid}
|
|
onChange={(e) => setAmountPaid(e.target.value)}
|
|
placeholder="0.00"
|
|
step="0.01"
|
|
min="0"
|
|
className="w-full px-4 py-2.5 rounded-md border border-border bg-background text-fg text-sm placeholder-muted focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
|
|
/>
|
|
</div>
|
|
|
|
{error && (
|
|
<div className="px-4 py-3 rounded-md bg-red-500/10 border border-red-500/30 text-sm text-red-400">
|
|
{error}
|
|
</div>
|
|
)}
|
|
|
|
<div className="flex justify-end gap-3 pt-2">
|
|
<button
|
|
type="button"
|
|
onClick={onClose}
|
|
className="px-4 py-2.5 rounded-md border border-border text-sm font-semibold text-fg hover:bg-surface-warm transition-colors"
|
|
>
|
|
Cancel
|
|
</button>
|
|
<button
|
|
type="submit"
|
|
disabled={saving}
|
|
className="px-6 py-2.5 rounded-md bg-indigo-600 hover:bg-indigo-500 text-white text-sm font-semibold transition-colors disabled:opacity-50"
|
|
>
|
|
{saving ? "Saving…" : "Save Filing"}
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// ── Main Component ────────────────────────────────────────────────────────────
|
|
|
|
export default function ComplianceSnapshot({ companyId, companyName, initialRecords, irp6Records, incomeTaxRecords }: Props) {
|
|
const [showFilingModal, setShowFilingModal] = useState(false);
|
|
const records = sortRecords(initialRecords);
|
|
const filedRecords = records.filter((r) => r.is_filed);
|
|
const lastThree = filedRecords.slice(0, 3);
|
|
const latestYear = filedRecords[0]?.ar_year;
|
|
const nonCompliant = records.find((r) => !r.is_filed && Boolean(r.ar_non_compliance_date));
|
|
|
|
return (
|
|
<>
|
|
<section data-od-id="company-compliance" className="bg-surface border border-border rounded-lg p-6 md:p-8">
|
|
<div className="flex flex-wrap items-start justify-between gap-4 mb-6">
|
|
<h2 className="text-xl font-semibold text-fg">Compliance snapshot</h2>
|
|
</div>
|
|
|
|
<div className="flex flex-col gap-5">
|
|
|
|
{/* ── 1. BizPortal ── */}
|
|
<div className="border border-border rounded-lg overflow-hidden">
|
|
<div className="bg-border-soft px-5 py-4 border-b border-border flex flex-wrap items-center justify-between gap-3">
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-8 h-8 rounded-lg bg-blue-500/10 border border-blue-500/20 flex items-center justify-center flex-shrink-0">
|
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
<rect x="2" y="2" width="5" height="5" rx="1" fill="#60a5fa" />
|
|
<rect x="9" y="2" width="5" height="5" rx="1" fill="#60a5fa" opacity="0.6" />
|
|
<rect x="2" y="9" width="5" height="5" rx="1" fill="#60a5fa" opacity="0.6" />
|
|
<rect x="9" y="9" width="5" height="5" rx="1" fill="#60a5fa" opacity="0.3" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-bold text-fg">BizPortal — CIPC Annual Returns</p>
|
|
<p className="text-xs text-muted">From ysterbaard_annual_returns</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="p-5">
|
|
{records.length === 0 ? (
|
|
<p className="text-sm text-muted py-2">No annual return records found for {companyName}.</p>
|
|
) : (
|
|
<div className="flex flex-col gap-5">
|
|
<div>
|
|
<p className="text-xs uppercase tracking-widest font-semibold text-muted mb-3">Last 3 submissions</p>
|
|
<div className="overflow-hidden rounded-md border border-border">
|
|
<table className="w-full text-sm">
|
|
<thead>
|
|
<tr className="bg-border-soft border-b border-border">
|
|
<th className="text-left px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Year</th>
|
|
<th className="text-left px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Month</th>
|
|
<th className="text-left px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Date Filed</th>
|
|
<th className="text-right px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Amount Paid</th>
|
|
<th className="text-left px-4 py-3 text-xs font-semibold text-muted uppercase tracking-wider">Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody className="divide-y divide-border">
|
|
{lastThree.length > 0 ? lastThree.map((ret) => (
|
|
<tr key={ret.id} className="hover:bg-surface-warm/50 transition-colors">
|
|
<td className="px-4 py-3 font-mono font-semibold text-fg">{ret.ar_year}</td>
|
|
<td className="px-4 py-3 text-fg capitalize">{ret.ar_month.toLowerCase()}</td>
|
|
<td className="px-4 py-3 font-mono text-muted text-xs">{formatDate(ret.date_filed)}</td>
|
|
<td className="px-4 py-3 text-right font-mono text-fg font-semibold">{formatAmount(ret.amount_paid)}</td>
|
|
<td className="px-4 py-3">{filedBadge(ret.is_filed)}</td>
|
|
</tr>
|
|
)) : (
|
|
<tr>
|
|
<td colSpan={5} className="px-4 py-4 text-center text-sm text-muted">No filed submissions yet.</td>
|
|
</tr>
|
|
)}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<div className="bg-surface-warm border border-border rounded-lg p-4">
|
|
<p className="text-xs font-semibold text-muted uppercase tracking-wider mb-1">Next submission date</p>
|
|
<p className="text-sm font-semibold text-fg">{getNextSubmissionDate(latestYear)}</p>
|
|
</div>
|
|
{nonCompliant ? (() => {
|
|
const d = new Date(nonCompliant.ar_non_compliance_date + "T00:00:00");
|
|
const now = new Date();
|
|
const months = (now.getFullYear() - d.getFullYear()) * 12 + (now.getMonth() - d.getMonth());
|
|
const overdueLabel = months <= 0 ? "< 1 month overdue" : `${months} month${months !== 1 ? "s" : ""} overdue`;
|
|
return (
|
|
<div className="bg-red-500/5 border border-red-500/20 rounded-lg p-4">
|
|
<p className="text-xs font-semibold text-red-400 uppercase tracking-wider mb-1">Non-compliance date</p>
|
|
<p className="text-sm font-semibold text-red-300">{formatDate(nonCompliant.ar_non_compliance_date)}</p>
|
|
<p className="text-xs text-red-500 mt-0.5">{overdueLabel}</p>
|
|
</div>
|
|
);
|
|
})() : (
|
|
<div className="bg-surface-warm border border-border rounded-lg p-4">
|
|
<p className="text-xs font-semibold text-muted uppercase tracking-wider mb-1">Non-compliance date</p>
|
|
<p className="text-sm text-muted">—</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* ── 2. SARS ── */}
|
|
<div className="border border-border rounded-lg overflow-hidden">
|
|
<div className="bg-border-soft px-5 py-4 border-b border-border flex flex-wrap items-center justify-between gap-3">
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-8 h-8 rounded-lg bg-indigo-500/10 border border-indigo-500/20 flex items-center justify-center flex-shrink-0">
|
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
|
<path d="M8 2L14 5v6l-6 3L2 11V5l6-3z" stroke="#818cf8" strokeWidth="1.5" strokeLinejoin="round" />
|
|
</svg>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-bold text-fg">SARS</p>
|
|
<p className="text-xs text-muted">IRP6 · Income Tax</p>
|
|
</div>
|
|
</div>
|
|
<button
|
|
onClick={() => setShowFilingModal(true)}
|
|
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md bg-indigo-600 hover:bg-indigo-500 text-white text-xs font-semibold transition-colors"
|
|
>
|
|
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
|
<path d="M6 1v10M1 6h10" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />
|
|
</svg>
|
|
Record New Filing
|
|
</button>
|
|
</div>
|
|
<div className="p-5">
|
|
<SARSReturnsSection irp6Records={irp6Records} incomeTaxRecords={incomeTaxRecords} />
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</section>
|
|
|
|
{showFilingModal && (
|
|
<NewFilingModal
|
|
companyId={companyId}
|
|
onClose={() => setShowFilingModal(false)}
|
|
onSuccess={() => {
|
|
setShowFilingModal(false);
|
|
window.location.reload();
|
|
}}
|
|
/>
|
|
)}
|
|
</>
|
|
);
|
|
}
|