346 lines
14 KiB
JavaScript
346 lines
14 KiB
JavaScript
import React, { useState } from "react";
|
||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
||
import { Button } from "@/components/ui/button";
|
||
import { Input } from "@/components/ui/input";
|
||
import { Label } from "@/components/ui/label";
|
||
import { Checkbox } from "@/components/ui/checkbox";
|
||
import { FileText, Download, Upload, Save, X } from "lucide-react";
|
||
import { Badge } from "@/components/ui/badge";
|
||
|
||
export default function W9FormViewer({ vendor, onClose }) {
|
||
const [formData, setFormData] = useState({
|
||
entity_name: vendor?.business_name || "",
|
||
business_name: "",
|
||
tax_classification: "",
|
||
llc_classification: "",
|
||
has_foreign_partners: false,
|
||
exempt_payee_code: "",
|
||
fatca_code: "",
|
||
address: "",
|
||
city_state_zip: "",
|
||
account_numbers: "",
|
||
ssn_part1: "",
|
||
ssn_part2: "",
|
||
ssn_part3: "",
|
||
ein_part1: "",
|
||
ein_part2: "",
|
||
tin_type: "ssn",
|
||
signature: "",
|
||
date: ""
|
||
});
|
||
|
||
const handleChange = (field, value) => {
|
||
setFormData(prev => ({ ...prev, [field]: value }));
|
||
};
|
||
|
||
const handleSave = () => {
|
||
// Save logic here
|
||
console.log("Saving W9 form:", formData);
|
||
onClose?.();
|
||
};
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
{/* Header with actions */}
|
||
<div className="flex items-center justify-between pb-4 border-b border-slate-200">
|
||
<div>
|
||
<div className="flex items-center gap-2 mb-1">
|
||
<FileText className="w-5 h-5 text-[#0A39DF]" />
|
||
<h3 className="font-bold text-lg text-[#1C323E]">Form W-9 (Rev. March 2024)</h3>
|
||
</div>
|
||
<p className="text-xs text-slate-500">Request for Taxpayer Identification Number and Certification</p>
|
||
</div>
|
||
<div className="flex gap-2">
|
||
<Button variant="outline" size="sm">
|
||
<Upload className="w-4 h-4 mr-2" />
|
||
Upload Signed
|
||
</Button>
|
||
<Button variant="outline" size="sm">
|
||
<Download className="w-4 h-4 mr-2" />
|
||
Download PDF
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Before you begin notice */}
|
||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||
<p className="text-sm font-semibold text-blue-900 mb-1">Before you begin</p>
|
||
<p className="text-xs text-blue-700">Give form to the requester. Do not send to the IRS.</p>
|
||
</div>
|
||
|
||
{/* Line 1 & 2 - Names */}
|
||
<div className="space-y-4">
|
||
<div>
|
||
<Label className="text-sm font-semibold">1. Name of entity/individual *</Label>
|
||
<p className="text-xs text-slate-500 mb-2">For a sole proprietor or disregarded entity, enter the owner's name on line 1</p>
|
||
<Input
|
||
value={formData.entity_name}
|
||
onChange={(e) => handleChange('entity_name', e.target.value)}
|
||
placeholder="Enter name as shown on your tax return"
|
||
className="font-medium"
|
||
/>
|
||
</div>
|
||
|
||
<div>
|
||
<Label className="text-sm font-semibold">2. Business name/disregarded entity name, if different from above</Label>
|
||
<Input
|
||
value={formData.business_name}
|
||
onChange={(e) => handleChange('business_name', e.target.value)}
|
||
placeholder="Enter business or DBA name (if applicable)"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Line 3a - Tax Classification */}
|
||
<div className="border border-slate-200 rounded-lg p-4 bg-slate-50">
|
||
<Label className="text-sm font-semibold mb-3 block">3a. Federal tax classification (Check only ONE box)</Label>
|
||
<div className="grid grid-cols-2 gap-3">
|
||
<div className="flex items-center space-x-2">
|
||
<Checkbox
|
||
checked={formData.tax_classification === "individual"}
|
||
onCheckedChange={(checked) => checked && handleChange('tax_classification', 'individual')}
|
||
/>
|
||
<Label className="text-sm font-normal cursor-pointer">Individual/sole proprietor</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Checkbox
|
||
checked={formData.tax_classification === "c_corp"}
|
||
onCheckedChange={(checked) => checked && handleChange('tax_classification', 'c_corp')}
|
||
/>
|
||
<Label className="text-sm font-normal cursor-pointer">C corporation</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Checkbox
|
||
checked={formData.tax_classification === "s_corp"}
|
||
onCheckedChange={(checked) => checked && handleChange('tax_classification', 's_corp')}
|
||
/>
|
||
<Label className="text-sm font-normal cursor-pointer">S corporation</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Checkbox
|
||
checked={formData.tax_classification === "partnership"}
|
||
onCheckedChange={(checked) => checked && handleChange('tax_classification', 'partnership')}
|
||
/>
|
||
<Label className="text-sm font-normal cursor-pointer">Partnership</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Checkbox
|
||
checked={formData.tax_classification === "trust"}
|
||
onCheckedChange={(checked) => checked && handleChange('tax_classification', 'trust')}
|
||
/>
|
||
<Label className="text-sm font-normal cursor-pointer">Trust/estate</Label>
|
||
</div>
|
||
<div className="flex items-center space-x-2 col-span-2">
|
||
<Checkbox
|
||
checked={formData.tax_classification === "llc"}
|
||
onCheckedChange={(checked) => checked && handleChange('tax_classification', 'llc')}
|
||
/>
|
||
<Label className="text-sm font-normal cursor-pointer">LLC</Label>
|
||
<span className="text-xs text-slate-500 mx-2">Enter tax classification:</span>
|
||
<Input
|
||
value={formData.llc_classification}
|
||
onChange={(e) => handleChange('llc_classification', e.target.value)}
|
||
placeholder="C, S, or P"
|
||
className="w-20 h-8"
|
||
maxLength={1}
|
||
/>
|
||
</div>
|
||
<div className="flex items-center space-x-2">
|
||
<Checkbox
|
||
checked={formData.tax_classification === "other"}
|
||
onCheckedChange={(checked) => checked && handleChange('tax_classification', 'other')}
|
||
/>
|
||
<Label className="text-sm font-normal cursor-pointer">Other (see instructions)</Label>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Line 3b */}
|
||
<div className="mt-4 pt-4 border-t border-slate-200">
|
||
<div className="flex items-start space-x-2">
|
||
<Checkbox
|
||
checked={formData.has_foreign_partners}
|
||
onCheckedChange={(checked) => handleChange('has_foreign_partners', checked)}
|
||
/>
|
||
<div>
|
||
<Label className="text-sm font-semibold cursor-pointer">3b. Foreign partners, owners, or beneficiaries</Label>
|
||
<p className="text-xs text-slate-500 mt-1">Check if you have any foreign partners, owners, or beneficiaries</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Line 4 - Exemptions */}
|
||
<div className="grid grid-cols-2 gap-4">
|
||
<div>
|
||
<Label className="text-sm font-semibold">4. Exempt payee code (if any)</Label>
|
||
<Input
|
||
value={formData.exempt_payee_code}
|
||
onChange={(e) => handleChange('exempt_payee_code', e.target.value)}
|
||
placeholder="See instructions"
|
||
className="mt-1"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label className="text-sm font-semibold">Exemption from FATCA reporting code (if any)</Label>
|
||
<Input
|
||
value={formData.fatca_code}
|
||
onChange={(e) => handleChange('fatca_code', e.target.value)}
|
||
placeholder="Applies to accounts outside US"
|
||
className="mt-1"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Lines 5-7 - Address */}
|
||
<div className="space-y-4">
|
||
<div>
|
||
<Label className="text-sm font-semibold">5. Address (number, street, and apt. or suite no.)</Label>
|
||
<Input
|
||
value={formData.address}
|
||
onChange={(e) => handleChange('address', e.target.value)}
|
||
placeholder="Enter street address"
|
||
className="mt-1"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label className="text-sm font-semibold">6. City, state, and ZIP code</Label>
|
||
<Input
|
||
value={formData.city_state_zip}
|
||
onChange={(e) => handleChange('city_state_zip', e.target.value)}
|
||
placeholder="City, State ZIP"
|
||
className="mt-1"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label className="text-sm font-semibold">7. List account number(s) here (optional)</Label>
|
||
<Input
|
||
value={formData.account_numbers}
|
||
onChange={(e) => handleChange('account_numbers', e.target.value)}
|
||
placeholder="Account numbers"
|
||
className="mt-1"
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Part I - TIN */}
|
||
<div className="border-2 border-slate-300 rounded-lg p-4 bg-white">
|
||
<h3 className="font-bold text-sm mb-4">Part I - Taxpayer Identification Number (TIN)</h3>
|
||
<p className="text-xs text-slate-600 mb-4">
|
||
Enter your TIN in the appropriate box. The TIN provided must match the name given on line 1 to avoid backup withholding.
|
||
</p>
|
||
|
||
<div className="space-y-4">
|
||
{/* SSN */}
|
||
<div>
|
||
<Label className="text-sm font-semibold mb-2 block">Social security number</Label>
|
||
<div className="flex items-center gap-2">
|
||
<Input
|
||
value={formData.ssn_part1}
|
||
onChange={(e) => handleChange('ssn_part1', e.target.value)}
|
||
maxLength={3}
|
||
placeholder="XXX"
|
||
className="w-20 text-center font-mono"
|
||
disabled={formData.tin_type === "ein"}
|
||
/>
|
||
<span className="text-lg">–</span>
|
||
<Input
|
||
value={formData.ssn_part2}
|
||
onChange={(e) => handleChange('ssn_part2', e.target.value)}
|
||
maxLength={2}
|
||
placeholder="XX"
|
||
className="w-16 text-center font-mono"
|
||
disabled={formData.tin_type === "ein"}
|
||
/>
|
||
<span className="text-lg">–</span>
|
||
<Input
|
||
value={formData.ssn_part3}
|
||
onChange={(e) => handleChange('ssn_part3', e.target.value)}
|
||
maxLength={4}
|
||
placeholder="XXXX"
|
||
className="w-24 text-center font-mono"
|
||
disabled={formData.tin_type === "ein"}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="text-center text-sm font-semibold text-slate-500">OR</div>
|
||
|
||
{/* EIN */}
|
||
<div>
|
||
<Label className="text-sm font-semibold mb-2 block">Employer identification number</Label>
|
||
<div className="flex items-center gap-2">
|
||
<Input
|
||
value={formData.ein_part1}
|
||
onChange={(e) => handleChange('ein_part1', e.target.value)}
|
||
maxLength={2}
|
||
placeholder="XX"
|
||
className="w-16 text-center font-mono"
|
||
disabled={formData.tin_type === "ssn"}
|
||
/>
|
||
<span className="text-lg">–</span>
|
||
<Input
|
||
value={formData.ein_part2}
|
||
onChange={(e) => handleChange('ein_part2', e.target.value)}
|
||
maxLength={7}
|
||
placeholder="XXXXXXX"
|
||
className="w-32 text-center font-mono"
|
||
disabled={formData.tin_type === "ssn"}
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Part II - Certification */}
|
||
<div className="border-2 border-slate-300 rounded-lg p-4 bg-yellow-50">
|
||
<h3 className="font-bold text-sm mb-3">Part II - Certification</h3>
|
||
<div className="text-xs text-slate-700 space-y-2 mb-4">
|
||
<p className="font-semibold">Under penalties of perjury, I certify that:</p>
|
||
<ol className="list-decimal list-inside space-y-1 pl-2">
|
||
<li>The number shown on this form is my correct taxpayer identification number (or I am waiting for a number to be issued to me); and</li>
|
||
<li>I am not subject to backup withholding because (a) I am exempt from backup withholding, or (b) I have not been notified by the IRS that I am subject to backup withholding as a result of a failure to report all interest or dividends, or (c) the IRS has notified me that I am no longer subject to backup withholding; and</li>
|
||
<li>I am a U.S. citizen or other U.S. person (defined below); and</li>
|
||
<li>The FATCA code(s) entered on this form (if any) indicating that I am exempt from FATCA reporting is correct.</li>
|
||
</ol>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-2 gap-4 mt-4">
|
||
<div>
|
||
<Label className="text-sm font-semibold">Signature of U.S. person *</Label>
|
||
<Input
|
||
value={formData.signature}
|
||
onChange={(e) => handleChange('signature', e.target.value)}
|
||
placeholder="Sign here"
|
||
className="mt-1 italic"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<Label className="text-sm font-semibold">Date *</Label>
|
||
<Input
|
||
type="date"
|
||
value={formData.date}
|
||
onChange={(e) => handleChange('date', e.target.value)}
|
||
className="mt-1"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Actions */}
|
||
<div className="flex justify-between items-center pt-4 border-t border-slate-200">
|
||
<Badge variant="outline" className="text-xs">
|
||
Form W-9 (Rev. 3-2024)
|
||
</Badge>
|
||
<div className="flex gap-3">
|
||
<Button variant="outline" onClick={onClose}>
|
||
Cancel
|
||
</Button>
|
||
<Button className="bg-[#0A39DF] hover:bg-[#0A39DF]/90" onClick={handleSave}>
|
||
<Save className="w-4 h-4 mr-2" />
|
||
Save W-9 Form
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
} |