From 5d9a0b217cafdfd9cfffa397a9cdebb1ec0e0080 Mon Sep 17 00:00:00 2001 From: Mahendra Choudhary Date: Sat, 24 May 2025 18:30:55 +0530 Subject: [PATCH 01/10] 006 invoice template --- src/templates/girnar.html | 167 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 src/templates/girnar.html diff --git a/src/templates/girnar.html b/src/templates/girnar.html new file mode 100644 index 0000000..36fe277 --- /dev/null +++ b/src/templates/girnar.html @@ -0,0 +1,167 @@ + + + + + + Tax Invoice + + + + +

TAX INVOICE

+ +
+

Vendor Details

+

Vendor Name: Acme Software Solutions Pvt Ltd.

+

Vendor Address: 123 Business Park, Sector 5, Mumbai

+

GSTIN: 12ABCDE1234F5Z6

+

State Name & Code: Maharashtra, Code: 400001

+

Invoice No: INV-1002

+

Invoice Date: 20/06/2024

+

PO Number: PO/ACME/202425/0457

+

MSME No.: -

+
+ +
+

Bill To

+

Company Name: Tech Solutions Pvt Limited

+

Address: 456 Corporate Tower, MG Road, Bengaluru

+

GSTIN: 29XYZAB8822C3D4

+

PAN: AAAAA1234A

+

State Name & Code: Karnataka, Code: 08

+
+ +
+

Details of Services Provided

+ + + + + + + + + + + + + + + + + + + + + + + +
Sl.Description of ServiceHSN/SACResource NameWorked DaysMonthTaxable Amount
1ROR/SW - software development service998314John Doe22May 2024Rs 200,000.00
+
+ +
+

Tax Summary

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tax TypeRateTaxable ValueTax Amount
SGST9%200,000.00 Rs18,000.00 Rs
CGST9%200,000.00 Rs18,000.00 Rs
Total Tax Amount36,000.00 Rs
+
+ +
+

Total Invoice Value (INR): Rs. 236,000.00

+

Amount in Words:

INR Two lakh thirty-six thousand rupees only +
+ +
+

Declaration

+

We declare that this invoice reflects the actual price of the services rendered and that all particulars stated herein are true and correct.

+

Mode of Payment: NEFT / RTGS / Cheque / UPI

+
+ +
+

Bank Details

+

Account Holder: Acme Software Solutions Pvt Ltd.

+

Bank Name: HDFC Bank

+

Account Number: 3456-7890-1234-56

+

Branch & IFSC Code: Main Branch, HDFC0000001

+
+ +
+

Authorized Signatory: [Authorized Signatory]

+
+ + + From ef021b71cf2d7ddf629b9b4ae31af2d97859d77d Mon Sep 17 00:00:00 2001 From: Mahendra Choudhary Date: Sat, 24 May 2025 19:01:11 +0530 Subject: [PATCH 02/10] added 006 template --- src/templates/GirnarTemplate.tsx | 134 +++++++++++++++++++++++++++++++ src/types/invoice.ts | 20 ++++- 2 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 src/templates/GirnarTemplate.tsx diff --git a/src/templates/GirnarTemplate.tsx b/src/templates/GirnarTemplate.tsx new file mode 100644 index 0000000..6552c02 --- /dev/null +++ b/src/templates/GirnarTemplate.tsx @@ -0,0 +1,134 @@ +/** + * @license + * Invoiceable - Open Source Invoice Builder + * Copyright (C) 2024 Mahendra Choudhary + * AGPL-3.0 License with commercial terms + * https://github.com/mandalorian99/invoiceable-web + */ +import { Invoice } from '../types/invoice'; + +export default function GirnarTemplate({ invoice }: { invoice: Invoice }) { + // Calculate totals + const subtotal = invoice.items.reduce((sum, item) => sum + (item.amount || 0), 0); + const taxAmount = invoice.taxes?.reduce((sum, tax) => sum + (tax.enabled ? tax.amount : 0), 0) || 0; + const total = subtotal + taxAmount; + + return ( +
+

TAX INVOICE

+ + {/* Vendor Details */} +
+

Vendor Details

+

Vendor Name: {invoice.from.name}

+

Vendor Address: {invoice.from.address}

+

GSTIN: {invoice.from.gstin}

+

Invoice No: {invoice.invoiceNumber}

+

Invoice Date: {invoice.date}

+
+ + {/* Bill To */} +
+

Bill To

+

Company Name: {invoice.to.name}

+

Address: {invoice.to.address}

+

GSTIN: {invoice.to.gstin}

+
+ + {/* Services Table */} +
+

Details of Services Provided

+ + + + + + + + + + + + + + {invoice.items.map((item, index) => ( + + + + + + + + + + ))} + +
Sl.DescriptionHSN/SACResourceDaysMonthAmount
{index + 1}{item.description}{item.hsnSac}{item.resourceName}{item.quantity}{item.period}₹{item.amount?.toLocaleString('en-IN')}
+
+ + {/* Tax Summary */} +
+

Tax Summary

+ + + + + + + + + + + {invoice.taxes?.map((tax) => ( + tax.enabled && ( + + + + + + + ) + ))} + + + + + +
Tax TypeRateTaxable ValueTax Amount
{tax.name}{tax.rate}%₹{subtotal.toLocaleString('en-IN')}₹{tax.amount.toLocaleString('en-IN')}
+ Total Tax Amount + + ₹{taxAmount.toLocaleString('en-IN')} +
+
+ + {/* Total Section */} +
+

+ Total Invoice Value (INR): ₹{total.toLocaleString('en-IN')} +

+

Amount in Words:

+

{invoice.amountInWords}

+
+ + {/* Declaration */} +
+

Declaration

+

We declare that this invoice reflects the actual price of the services rendered and that all particulars stated herein are true and correct.

+

Mode of Payment: {invoice.paymentMode || 'NEFT / RTGS / Cheque / UPI'}

+
+ + {/* Bank Details */} +
+

Bank Details

+

Account Holder: {invoice.bankDetails?.accountName}

+

Account Number: {invoice.bankDetails?.accountNumber}

+

IFSC Code: {invoice.bankDetails?.ifscCode}

+
+ + {/* Signature */} +
+

Authorized Signatory: {invoice.signatory}

+
+
+ ); +} \ No newline at end of file diff --git a/src/types/invoice.ts b/src/types/invoice.ts index f0248e3..9cc7dc7 100644 --- a/src/types/invoice.ts +++ b/src/types/invoice.ts @@ -107,11 +107,13 @@ export interface Invoice { name: string; email: string; address: string; + gstin?: string; }; to: { name: string; email: string; address: string; + gstin?: string; }; items: InvoiceItem[]; notes: string; @@ -121,6 +123,14 @@ export interface Invoice { taxes?: InvoiceTax[]; // Added tax information taxEnabled?: boolean; // Flag to toggle tax display currency: string; + bankDetails?: { + accountName: string; + accountNumber: string; + ifscCode: string; + }; + signatory?: string; + amountInWords?: string; + paymentMode?: string; } export interface InvoiceTemplateData { @@ -171,5 +181,13 @@ export const defaultInvoice: Invoice = { templateConfig: 'hourly', taxes: [], taxEnabled: false, - currency: '$' + currency: '$', + bankDetails: { + accountName: 'Account Name', + accountNumber: '1234567890', + ifscCode: 'IFSC1234567' + }, + signatory: 'John Doe', + amountInWords: 'One thousand twenty-four dollars and fifty cents', + paymentMode: 'NEFT / RTGS / Cheque / UPI' }; \ No newline at end of file From 0634d321350fed8a3e59136ea3dae6ad607f6340 Mon Sep 17 00:00:00 2001 From: Mahendra Choudhary Date: Sat, 24 May 2025 19:03:28 +0530 Subject: [PATCH 03/10] generate 006 config --- src/config/girnarConfig.ts | 127 +++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src/config/girnarConfig.ts diff --git a/src/config/girnarConfig.ts b/src/config/girnarConfig.ts new file mode 100644 index 0000000..1709a87 --- /dev/null +++ b/src/config/girnarConfig.ts @@ -0,0 +1,127 @@ +/** + * @license + * Invoiceable - Open Source Invoice Builder + * Copyright (C) 2024 Mahendra Choudhary + * AGPL-3.0 License with commercial terms + * https://github.com/mandalorian99/invoiceable-web + */ +import { InvoiceTemplateConfig } from '../types/invoice'; +import { TAX_TYPES, getAvailableTaxesForTemplate } from './taxConfig'; + +export const girnarConfig: InvoiceTemplateConfig = { + id: 'girnar', + name: 'GST Invoice', + description: 'Professional GST-compliant invoice template for Indian businesses', + industry: 'it', + previewImage: 'https://images.unsplash.com/photo-1604594849809-4f9d0f738d2c?q=80&w=3082&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D', + + itemFields: [ + { + key: 'description', + label: 'Service Description', + type: 'text', + required: true, + validation: { + minLength: 10, + maxLength: 200 + } + }, + { + key: 'hsnSac', + label: 'HSN/SAC Code', + type: 'text', + required: true, + validation: { + pattern: '^[0-9]{6,8}$' + } + }, + { + key: 'resourceName', + label: 'Resource Name', + type: 'text', + required: true, + validation: { + minLength: 2, + maxLength: 50 + } + }, + { + key: 'workedDays', + label: 'Worked Days', + type: 'number', + required: true, + validation: { + min: 1, + max: 31 + } + }, + { + key: 'period', + label: 'Service Month', + type: 'text', + required: true, + validation: { + pattern: '^(January|February|March|April|May|June|July|August|September|October|November|December) \\d{4}$' + } + }, + { + key: 'amount', + label: 'Taxable Amount', + type: 'calculated', + calculate: (fields) => fields.rate * fields.workedDays + } + ], + + validationRules: { + custom: [ + { + condition: (items) => items.every(item => item.hsnSac?.match(/^[0-9]{6,8}$/)), + message: 'Valid 6-8 digit HSN/SAC code required' + }, + { + condition: (items) => items.every(item => item.workedDays >= 1), + message: 'Minimum 1 working day required per service item' + } + ] + }, + + defaultNotes: 'Payment terms: Net 15 days\nLate payment fee: 1.5% monthly interest', + + taxes: { + enabled: true, + config: { + taxCalculation: (subtotal, selectedTaxes) => { + const taxAmount = selectedTaxes.reduce((sum, tax) => + sum + (tax.isPercentage ? (subtotal * tax.rate / 100) : tax.rate), 0); + return { + taxAmount, + total: subtotal + taxAmount, + taxes: selectedTaxes + }; + }, + availableTaxes: [ + { + id: 'sgst', + name: 'SGST', + description: 'State Goods and Services Tax', + defaultRate: 9, + isPercentage: true + }, + { + id: 'cgst', + name: 'CGST', + description: 'Central Goods and Services Tax', + defaultRate: 9, + isPercentage: true + } + ] + } + }, + + meta: { + accentColor: '#1e40af', + legalFields: ['gstin', 'pan', 'bankDetails'], + requiredFields: ['hsnSac', 'resourceName'], + paymentModes: ['NEFT', 'RTGS', 'Cheque', 'UPI'] + } +}; \ No newline at end of file From d49f5856003b3d083baf0defad58631fee3d11c8 Mon Sep 17 00:00:00 2001 From: Mahendra Choudhary Date: Sun, 25 May 2025 17:10:42 +0530 Subject: [PATCH 04/10] updae config --- src/config/girnarConfig.ts | 17 +++++++++++++++-- src/types/invoice.ts | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/config/girnarConfig.ts b/src/config/girnarConfig.ts index 1709a87..745812d 100644 --- a/src/config/girnarConfig.ts +++ b/src/config/girnarConfig.ts @@ -45,6 +45,16 @@ export const girnarConfig: InvoiceTemplateConfig = { maxLength: 50 } }, + { + key: 'rate', + label: 'Daily Rate', + type: 'number', + required: true, + validation: { + min: 0, + max: 100000 + } + }, { key: 'workedDays', label: 'Worked Days', @@ -67,8 +77,11 @@ export const girnarConfig: InvoiceTemplateConfig = { { key: 'amount', label: 'Taxable Amount', - type: 'calculated', - calculate: (fields) => fields.rate * fields.workedDays + type: 'number', + required: true, + validation: { + min: 0 + } } ], diff --git a/src/types/invoice.ts b/src/types/invoice.ts index 9cc7dc7..7ea3c30 100644 --- a/src/types/invoice.ts +++ b/src/types/invoice.ts @@ -117,7 +117,7 @@ export interface Invoice { }; items: InvoiceItem[]; notes: string; - template: 'modern' | 'minimal' | 'professional' | 'freelancer' | 'legion'; + template: 'modern' | 'minimal' | 'professional' | 'freelancer' | 'legion' | 'girnar'; invoiceType: 'hourly' | 'fixed_term'; templateConfig: string; // Reference to template config ID taxes?: InvoiceTax[]; // Added tax information From eb7e6ee79042f235b7db0d79a9720dbb8614d004 Mon Sep 17 00:00:00 2001 From: Mahendra Choudhary Date: Sun, 25 May 2025 17:14:14 +0530 Subject: [PATCH 05/10] integratign template 006 with app --- src/components/InvoicePreview.tsx | 11 ++++++-- src/config/invoiceTemplates.ts | 45 ++++++++++++++++++++++++++++++- src/config/templates/index.ts | 38 ++++++++++++++++++++++++++ src/templates/templateStrings.ts | 40 ++++++++++++++++++++++++++- 4 files changed, 130 insertions(+), 4 deletions(-) diff --git a/src/components/InvoicePreview.tsx b/src/components/InvoicePreview.tsx index 32730d9..8eb1fee 100644 --- a/src/components/InvoicePreview.tsx +++ b/src/components/InvoicePreview.tsx @@ -12,6 +12,7 @@ import ProfessionalTemplate from '../templates/ProfessionalTemplate'; import FreelancerTemplate from '../templates/FreelancerTemplate'; import { forwardRef } from 'react'; import LegionTemplate from '../templates/LegionTemplate'; +import GirnarTemplate from '../templates/GirnarTemplate'; interface Props { invoice: Invoice; @@ -23,7 +24,8 @@ const InvoicePreview = forwardRef(({ invoice }, ref) => { minimal: MinimalTemplate, professional: ProfessionalTemplate, freelancer: FreelancerTemplate, - legion: LegionTemplate + legion: LegionTemplate, + girnar: GirnarTemplate }; // Rendering the template based on the invoice templates @@ -36,7 +38,12 @@ const InvoicePreview = forwardRef(({ invoice }, ref) => { t.enabled) || [] + taxes: invoice.taxes?.filter(t => t.enabled) || [], + bankDetails: invoice.bankDetails || { + accountName: '', + accountNumber: '', + ifscCode: '' + } }} /> diff --git a/src/config/invoiceTemplates.ts b/src/config/invoiceTemplates.ts index a15c774..b5c6515 100644 --- a/src/config/invoiceTemplates.ts +++ b/src/config/invoiceTemplates.ts @@ -11,11 +11,54 @@ import { minimalConfig } from './minimalConfig'; import { professionalConfig } from './professionalConfig'; import { legionConfig } from './legionConfig'; import { freelancerConfig } from './freelancerConfig'; +import { girnarConfig } from './girnarConfig'; + +/** + * Invoice Template Configuration Registry + * + * Aggregates all template configurations for the invoice builder. Provides: + * - Template metadata and display properties + * - Field definitions for invoice line items + * - Tax calculation configurations + * - Validation rules and business logic + * + * Template Key | Primary Use Case | Special Features + * ------------------------------------------------- + * modern | General business | Dynamic tax calculations + * minimal | Quick invoices | Simplified layout + * professional | Corporate | Legal field support + * legion | Contract work | 15-day billing cycles + * freelancer | Consulting | Flexible time tracking + * girnar | GST compliance | HSN/SAC code support + * + * Configuration Structure: + * - itemFields: Defines data structure for line items + * - Supported types: text/number/calculated + * - Validation rules per field + * - taxes: Tax handling configuration + * - Enabled/disabled state + * - Calculation methodology + * - Available tax types + * - validationRules: Custom business logic constraints + * - meta: Presentation preferences + * + * Usage Notes: + * 1. New templates require: + * - Configuration file in src/config + * - Import statement in this registry + * - Entry in TEMPLATE_CONFIGS object + * 2. Template IDs must be unique + * 3. Maintain interface compatibility + */ + + export const TEMPLATE_CONFIGS: Record = { modern: modernConfig, minimal: minimalConfig, professional: professionalConfig, legion: legionConfig, - freelancer: freelancerConfig + freelancer: freelancerConfig, + girnar: girnarConfig, + // add new templates here }; \ No newline at end of file diff --git a/src/config/templates/index.ts b/src/config/templates/index.ts index 95e91f8..5600ced 100644 --- a/src/config/templates/index.ts +++ b/src/config/templates/index.ts @@ -5,12 +5,49 @@ * AGPL-3.0 License with commercial terms * https://github.com/mandalorian99/invoiceable-web */ + +/** + * Invoice Template Registry + * + * Central configuration hub for invoice templates. This file: + * - Aggregates all template configurations + * - Serves as the single source of truth for available templates + * - Enables template discovery across the application + * + * Template Structure Requirements: + * - Must implement InvoiceTemplateConfig interface + * - Require unique template ID (lowercase, no spaces) + * - Need corresponding HTML template in templates directory + * - Should include preview image URL + * + * Adding New Templates: + * 1. Create config file in src/config/[templateName]Config.ts + * 2. Import configuration in this file + * 3. Add entry to TEMPLATE_CONFIGS object below + * + * Example: + * import { newTemplateConfig } from '../newTemplateConfig'; + * TEMPLATE_CONFIGS: { ..., newTemplate: newTemplateConfig } + * + * Required Checks: + * - Template ID must be unique + * - All required interface fields implemented + * - Corresponding HTML template exists + * - Preview image accessible via URL + * + * Configuration Validation: + * - itemFields must have at least description and amount + * - Tax calculations must handle percentage/flat rates + * - Validation rules should cover common edge cases + */ + import { modernConfig } from '../modernConfig'; import { minimalConfig } from '../minimalConfig'; import { InvoiceTemplateConfig } from '../../types/invoice'; import { professionalConfig } from '../professionalConfig'; import { freelancerConfig } from '../freelancerConfig'; import { legionConfig } from '../legionConfig'; +import { girnarConfig } from '../girnarConfig'; // Import other template configs here export const TEMPLATE_CONFIGS: Record = { @@ -19,5 +56,6 @@ export const TEMPLATE_CONFIGS: Record = { professional: professionalConfig, freelancer: freelancerConfig, legion: legionConfig, + girnar: girnarConfig, // Add other templates }; \ No newline at end of file diff --git a/src/templates/templateStrings.ts b/src/templates/templateStrings.ts index b7b0a2d..6df1d3c 100644 --- a/src/templates/templateStrings.ts +++ b/src/templates/templateStrings.ts @@ -6,14 +6,52 @@ * https://github.com/mandalorian99/invoiceable-web */ +/** + * Template String Registry + * + * Central repository for HTML templates used by the invoice generator. Each template + * is imported as a raw HTML string and made available to the Mustache template engine + * via the pdfGenerator module. + * + * Key Responsibilities: + * - Import raw HTML templates from external files + * - Export template strings with standardized naming convention + * - Provide template availability for PDF generation workflow + * + * Template Requirements: + * 1. Must use Mustache-style placeholders ({{property}}) + * 2. Should reference properties from InvoiceTemplateData interface + * 3. Must maintain HTML structure compatible with html2pdf + * + * Usage in PDF Generation: + * @see pdfGenerator.ts - Uses these template strings with Mustache.render() + * to generate final HTML for PDF conversion + * + * Adding New Templates: + * 1. Create new .html file in templates directory + * 2. Import as raw string: import newTemplateHtml from './new.html?raw'; + * 3. Export with naming convention: export const newTemplateString = newTemplateHtml; + * + * Current Available Templates: + * - modern: General business invoices + * - minimal: Simplified layout for quick invoices + * - professional: Corporate-style with legal sections + * - freelancer: Time-based consulting format + * - legion: 15-day billing cycle contracts + * - girnar: GST-compliant Indian format + */ + + import modernHtml from './modern.html?raw'; import minimalHtml from './minimal.html?raw'; import professionalHtml from './professional.html?raw'; import freelancerHtml from './freelancer.html?raw'; import legionHtml from './legion.html?raw'; +import girnarHtml from './girnar.html?raw'; export const modernTemplateString = modernHtml; export const minimalTemplateString = minimalHtml; export const professionalTemplateString = professionalHtml; export const freelancerTemplateString = freelancerHtml; -export const legionTemplateString = legionHtml; \ No newline at end of file +export const legionTemplateString = legionHtml; +export const girnarTemplateString = girnarHtml; \ No newline at end of file From e50d285e29b8ac4082dba53b288fc983cabd9d63 Mon Sep 17 00:00:00 2001 From: Mahendra Choudhary Date: Sun, 25 May 2025 17:16:14 +0530 Subject: [PATCH 06/10] update export and invoice form for006 specific changes --- src/components/ExportPDFButton.tsx | 7 ++++- src/components/InvoiceForm.tsx | 49 ++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/components/ExportPDFButton.tsx b/src/components/ExportPDFButton.tsx index 77214f2..90df6a0 100644 --- a/src/components/ExportPDFButton.tsx +++ b/src/components/ExportPDFButton.tsx @@ -115,7 +115,12 @@ const ExportPDFButton: React.FC = ({ invoice }) => { }; }), taxEnabled: templateConfig.taxes.enabled, - notes: invoice.notes + notes: invoice.notes, + bankDetails: invoice.bankDetails || { + accountName: '', + accountNumber: '', + ifscCode: '' + } }; // Generate PDF using the invoice's template style diff --git a/src/components/InvoiceForm.tsx b/src/components/InvoiceForm.tsx index f6ed9f4..c73451a 100644 --- a/src/components/InvoiceForm.tsx +++ b/src/components/InvoiceForm.tsx @@ -53,7 +53,11 @@ export default function InvoiceForm({ invoice, onInvoiceChange }: Props) { let subtotal = 0; // Different templates might use different item structures - if (invoice.template === 'freelancer') { + if (invoice.template === 'girnar') { + // Girnar template uses workedDays * rate + subtotal = invoice.items.reduce((sum, item) => + sum + (item.amount || (item.workedDays * item.rate) || 0), 0); + } else if (invoice.template === 'freelancer') { // Freelancer template uses rate and hours subtotal = invoice.items.reduce((sum, item) => sum + (item.amount || (item.rate * item.hours) || 0), 0); @@ -122,7 +126,18 @@ export default function InvoiceForm({ invoice, onInvoiceChange }: Props) { const updatedItem = { ...item, [field]: value }; - // Auto-calculate calculated fields + // Girnar-specific auto-calculation + if (invoice.template === 'girnar' && (field === 'rate' || field === 'workedDays')) { + const rate = parseFloat(updatedItem.rate) || 0; + const workedDays = parseFloat(updatedItem.workedDays) || 0; + + // Only auto-calculate if amount hasn't been manually modified + if (!updatedItem.amount || updatedItem.amount === rate * workedDays) { + updatedItem.amount = rate * workedDays; + } + } + + // Existing calculation logic for other templates TEMPLATE_CONFIGS[invoice.template].itemFields.forEach(configField => { if (configField.type === 'calculated' && configField.calculate) { updatedItem[configField.key] = configField.calculate(updatedItem); @@ -175,7 +190,11 @@ export default function InvoiceForm({ invoice, onInvoiceChange }: Props) { let subtotal = 0; // Different templates might use different item structures - if (invoice.template === 'freelancer') { + if (invoice.template === 'girnar') { + // Girnar template uses workedDays * rate + subtotal = invoice.items.reduce((sum, item) => + sum + (item.amount || (item.workedDays * item.rate) || 0), 0); + } else if (invoice.template === 'freelancer') { // Freelancer template uses rate and hours subtotal = invoice.items.reduce((sum, item) => sum + (item.amount || (item.rate * item.hours) || 0), 0); @@ -297,6 +316,18 @@ export default function InvoiceForm({ invoice, onInvoiceChange }: Props) { className="block w-full rounded-lg border-gray-300 shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all" rows={3} /> + {invoice.template === 'girnar' && ( + onInvoiceChange({ + ...invoice, + from: { ...invoice.from, gstin: e.target.value } + })} + className="block w-full rounded-lg border-gray-300 shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all" + /> + )} @@ -337,6 +368,18 @@ export default function InvoiceForm({ invoice, onInvoiceChange }: Props) { className="block w-full rounded-lg border-gray-300 shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all" rows={3} /> + {invoice.template === 'girnar' && ( + onInvoiceChange({ + ...invoice, + to: { ...invoice.to, gstin: e.target.value } + })} + className="block w-full rounded-lg border-gray-300 shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all" + /> + )} From beb77be814bc0a6cd97b129692e0e78021eb9ade Mon Sep 17 00:00:00 2001 From: Aaditya Choudhary Date: Tue, 10 Feb 2026 16:10:56 +0530 Subject: [PATCH 07/10] template-issues --- src/components/InvoiceForm.tsx | 291 ++++++++++++++++++++- src/config/girnarConfig.ts | 7 +- src/config/taxConfig.ts | 29 ++- src/config/visualTemplates.ts | 3 +- src/templates/FreelancerTemplate.tsx | 19 ++ src/templates/GirnarTemplate.tsx | 242 +++++++++++++++--- src/templates/LegionTemplate.tsx | 24 +- src/templates/MinimalTemplate.tsx | 19 ++ src/templates/ModernTemplate.tsx | 19 ++ src/templates/ProfessionalTemplate.tsx | 19 ++ src/templates/freelancer.html | 23 ++ src/templates/girnar.html | 339 ++++++++++++++----------- src/templates/legion.html | 20 ++ src/templates/minimal.html | 22 ++ src/templates/modern.html | 20 ++ src/templates/professional.html | 20 ++ src/types/invoice.ts | 40 +-- 17 files changed, 925 insertions(+), 231 deletions(-) diff --git a/src/components/InvoiceForm.tsx b/src/components/InvoiceForm.tsx index c73451a..d4eceab 100644 --- a/src/components/InvoiceForm.tsx +++ b/src/components/InvoiceForm.tsx @@ -158,6 +158,46 @@ export default function InvoiceForm({ invoice, onInvoiceChange }: Props) { }); }; + //toggle grinar display + const toggleGrinar = (enabled: boolean) => { + onInvoiceChange({ + ...invoice, + girnarEnabled: enabled, + declaration:enabled ? invoice.declaration :undefined + }); + }; + + //toggle pay mode display + const togglePay = (enabled: boolean) => { + onInvoiceChange({ + ...invoice, + payEnabled: enabled, + paymentMode: enabled ? invoice.paymentMode : undefined + }); + }; + + + + //toggle sign display + const toggleSignature = (enabled: boolean) => { + onInvoiceChange({ + ...invoice, + signEnabled: enabled, + signatory:enabled ? invoice.signatory:undefined + }); + }; + + + //toggle bank display + const toggleBankDetails = (enabled: boolean) => { + onInvoiceChange({ + ...invoice, + bDetailsEnabled: enabled, + bankDetails:enabled ? invoice.bankDetails:undefined + }); + + }; + // Update tax rate const updateTaxRate = (taxId: string, rate: number) => { if (!invoice.taxes) return; @@ -329,6 +369,7 @@ export default function InvoiceForm({ invoice, onInvoiceChange }: Props) { /> )} + {/* To Section */} @@ -380,9 +421,8 @@ export default function InvoiceForm({ invoice, onInvoiceChange }: Props) { className="block w-full rounded-lg border-gray-300 shadow-sm focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-all" /> )} - - +<<<<<<< HEAD {/* Service Period */} {invoice.template === 'legion' && (
@@ -412,6 +452,21 @@ export default function InvoiceForm({ invoice, onInvoiceChange }: Props) { onRemoveItem={removeItem} onUpdateItem={updateItem} /> +======= + + +
+ + + + +>>>>>>> b3ff24d (template-issues) {/* Tax Section */} {taxesEnabled && ( @@ -486,6 +541,238 @@ export default function InvoiceForm({ invoice, onInvoiceChange }: Props) { )} + {/* declaration */} + + + + + + + + + + + {/* for declaration */} + + +