Skip to content

Conversation

@sandaru-sdm
Copy link
Contributor

@sandaru-sdm sandaru-sdm commented Jul 28, 2025

🎯 Fixes Issue #3

This PR implements a dark/light theme toggle feature with localStorage persistence as requested.

✨ Features Implemented

  • βœ… CSS Variables: Clean theme system using CSS custom properties
  • βœ… Toggle Button: Simple moon/sun icon toggle in navbar
  • βœ… localStorage Persistence: Theme preference saved across sessions
  • βœ… Smooth Transitions: 0.3s ease transitions between themes
  • βœ… Both Pages: Theme toggle works on home and invoice pages

🎨 Theme Design

  • Light Theme: Clean whites/grays with blue accents
  • Dark Theme: Modern dark slate with purple accents
  • Icons: Moon for light mode, Sun for dark mode

πŸ§ͺ Testing Done

  • Theme toggle functionality
  • localStorage persistence across page refreshes
  • Responsive design compatibility
  • Both home and invoice pages work correctly

πŸ“± User Experience

The theme toggle improves UX by:

  • Providing comfortable viewing in different lighting conditions
  • Maintaining user preference across sessions
  • Adding a modern, professional touch to the interface
  • Following current web design trends

Ready for review! This enhancement makes the GenInvoice app more accessible and user-friendly. πŸš€

Summary by CodeRabbit

  • New Features

    • Introduced light and dark theme support with a toggle button for dynamic theming across all pages.
    • Enhanced navigation with improved structure, sticky positioning, and animated hover effects.
    • Redesigned invoice form and preview for improved accessibility, responsiveness, and modern layout.
    • Added animated and visually distinct buttons for actions like login, theme toggle, row management, and PDF download.
  • Style

    • Unified and modernized visual design with CSS variables, transitions, and responsive layouts.
    • Improved typography, spacing, and visual hierarchy for better readability and user experience.
  • Bug Fixes

    • Refined form input synchronization and preview updates for more robust and accurate data display.
  • Refactor

    • Modularized and centralized JavaScript event handling for maintainability and reliability.
    • Reorganized HTML structure for semantic clarity and accessibility.
  • Chores

    • Removed unused or obsolete code and streamlined script placement for better performance and clarity.

@vercel
Copy link

vercel bot commented Jul 28, 2025

@sandaru-sdm is attempting to deploy a commit to the Eshita's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link

coderabbitai bot commented Jul 28, 2025

"""

Walkthrough

The changes implement a comprehensive redesign of the application's UI and JavaScript logic. CSS files are refactored for theme support, responsiveness, and animation. HTML files are modernized for semantic structure, accessibility, and new UI controls like a theme toggle. JavaScript is modularized, event handling is centralized, and preview synchronization is improved.

Changes

Cohort / File(s) Change Summary
Global Theming & Responsive CSS
home.css, style.css
Refactored to use CSS variables for light/dark themes, with variables scoped to :root and body.dark-theme. Enhanced transitions, added sticky navbar, improved navigation and button styles, introduced animations, and unified structure. Responsive media queries and grid layouts improve usability on mobile. All styles are now theme-aware and visually polished.
Homepage Structure & UI
index.html
Header structure updated for semantic clarity; navigation links now use a <nav> element. Theme toggle button with SVG icons added. Inline styles removed; scripts reorganized for clarity. The main heading's highlight is now a styled span. Old, commented, and redundant code removed.
Invoice Page Refactor
invoice.html
Major overhaul of markup for semantic, accessible, and flexible layout. Tables replaced with div-based grids and groups for forms and preview. Navigation and theme toggle updated to match homepage. Form fields grouped and labeled; invoice items table restructured for consistency. Preview section reorganized for clarity. Download button restyled and repositioned. No changes to functional bindings or field IDs.
JavaScript Modularization & UI Sync
script.js
Refactored to modularize event listeners and theme application. Centralized all event binding, introduced functions for applying saved themes, synchronizing form and preview, and row management. Improved robustness with checks, enhanced preview update logic, and consistent currency/tax updates. PDF download logic improved for safety and options. Removed inline event listeners in favor of programmatic setup.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Browser
    participant JS (script.js)
    participant Storage

    User->>Browser: Loads page (index.html or invoice.html)
    Browser->>JS (script.js): Executes on DOMContentLoaded
    JS (script.js)->>Storage: Reads saved theme from localStorage
    JS (script.js)->>Browser: Applies theme class, updates icons
    JS (script.js)->>Browser: Sets up event listeners (theme toggle, form, buttons)
    User->>Browser: Interacts with form (inputs, add/delete rows)
    Browser->>JS (script.js): Triggers input/change events
    JS (script.js)->>Browser: Syncs form values to preview
    User->>Browser: Clicks theme toggle
    Browser->>JS (script.js): Toggles theme, updates localStorage
    JS (script.js)->>Browser: Updates theme class and icons
    User->>Browser: Clicks Download PDF
    Browser->>JS (script.js): Triggers PDF generation
    JS (script.js)->>Browser: Uses html2pdf to download preview
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

πŸ‡βœ¨
With themes that shift from night to day,
And layouts flex in modern way,
The scripts now dance in tidy rows,
While buttons bounce and preview glows.
Responsive grids, new styles unfurledβ€”
This rabbit’s proud to style your world!
πŸŒ™πŸŒžπŸ’»
"""

Note

⚑️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • πŸ“ Generate Docstrings
πŸ§ͺ Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❀️ Share
πŸͺ§ Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
invoice.html (1)

309-317: Consider adding loading state for PDF generation

While the download button placement is good, consider adding a loading indicator since PDF generation can take time.

You might want to add a loading spinner or disable the button during PDF generation to provide better user feedback.

style.css (1)

374-381: Consider theme-aware invoice preview

The invoice preview has hardcoded white background and dark text colors. While this ensures printability, users might expect the preview to follow the theme.

Consider adding a print-specific class or media query to ensure white background only for printing:

.invoice-box {
-  background-color: white;
-  color: #111827;
+  background-color: var(--preview-bg);
+  color: var(--text-color);
  padding: 2rem;
  border-radius: 8px;
  font-family: Arial, sans-serif;
  font-size: 0.9rem;
  line-height: 1.4;
}

+@media print {
+  .invoice-box {
+    background-color: white;
+    color: #111827;
+  }
+}
script.js (2)

11-11: Consider fallback for optional chaining

The optional chaining operator ?. might not be supported in older browsers.

For broader browser compatibility:

-  const savedTheme = window.localStorage?.getItem("theme") || "light";
+  const savedTheme = (window.localStorage && window.localStorage.getItem("theme")) || "light";

41-49: Add error handling for localStorage

Consider wrapping localStorage operations in try-catch blocks to handle potential exceptions (e.g., when storage is full or disabled).

 if (document.body.classList.contains("dark-theme")) {
-  if (window.localStorage) {
-    window.localStorage.setItem("theme", "dark");
-  }
+  try {
+    window.localStorage?.setItem("theme", "dark");
+  } catch (e) {
+    console.warn("Failed to save theme preference:", e);
+  }
   moonIcon.style.display = "none";
   sunIcon.style.display = "block";
 } else {
-  if (window.localStorage) {
-    window.localStorage.setItem("theme", "light");
-  }
+  try {
+    window.localStorage?.setItem("theme", "light");
+  } catch (e) {
+    console.warn("Failed to save theme preference:", e);
+  }
   moonIcon.style.display = "block";
   sunIcon.style.display = "none";
 }
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between d13f92d and 6df9a5d.

πŸ“’ Files selected for processing (5)
  • home.css (1 hunks)
  • index.html (1 hunks)
  • invoice.html (1 hunks)
  • script.js (4 hunks)
  • style.css (1 hunks)
πŸ”‡ Additional comments (15)
index.html (4)

17-19: Good semantic structure for logo styling

Wrapping the logo in a div provides better control for styling and animations.


21-24: Excellent semantic navigation structure

The use of a semantic <nav> element improves accessibility and removes unnecessary inline styles.


25-40: Well-implemented theme toggle button

The SVG icons are properly embedded with appropriate initial visibility states. The implementation aligns perfectly with the PR objectives for dark mode toggle functionality.


56-61: Good script organization

Moving the navigation function inline and adding the external script reference improves code organization and enables the theme toggle functionality.

invoice.html (3)

26-41: Consistent theme toggle implementation

The theme toggle button matches the implementation in index.html, ensuring a consistent user experience across pages.


54-94: Excellent form structure with CSS Grid

The transition from table-based to grid-based layout significantly improves responsiveness and maintainability. The semantic grouping of form fields enhances accessibility.


182-197: Smart use of HTML template element

Using a <template> element for the row template is a best practice that prevents the template from being rendered and provides clean cloning for new rows.

home.css (3)

1-31: Well-structured theme variables

Excellent implementation of CSS custom properties for theming. The variable naming is clear and the color palette provides good visual hierarchy for both light and dark themes.


112-129: Creative theme toggle animation

The scale and rotation effects on hover provide nice visual feedback. The background color on hover enhances the interactive feel.


162-250: Smooth entrance animations

The staggered animations create an elegant page load experience. The use of both fill mode ensures elements retain their final state.

style.css (2)

1-55: Consistent theme implementation

The theme variables perfectly align with home.css, ensuring a cohesive experience across the application. The dark theme colors are well-chosen for readability.


569-678: Comprehensive responsive design

The media queries provide excellent coverage for various device sizes. The layout adjustments ensure usability across all viewports.

script.js (3)

9-28: Robust theme persistence implementation

Good implementation with localStorage and proper null checks. The theme application on page load ensures persistence across sessions as per PR objectives.


190-202: Excellent use of template cloning

Using the template element and cloning its content is the correct approach for adding new rows. This ensures clean, event-free elements.


282-285: Good defensive programming

Checking for both the DOM element and the html2pdf library presence prevents runtime errors. The user-friendly alert message is helpful.

Comment on lines +194 to +197
background: linear-gradient(135deg, var(--text-color), var(--highlight-color));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’‘ Verification agent

🧩 Analysis chain

Verify text gradient browser compatibility

The gradient text effect using -webkit-background-clip: text might not work in all browsers.


🌐 Web query:

What is the current browser support for CSS gradient text using -webkit-background-clip: text property?

πŸ’‘ Result:

CSS gradient text using -webkit-background-clip: text is fully supported in all major Chromium-based browsers (Chrome, Edge, Opera, Samsung Internet) and in Safari (macOS and iOS), but remains unsupported in Firefox as of July 2025.[10]

Details:

  • Supported browsers:

    • Chrome (desktop and Android): Full support for many years. Requires both -webkit-background-clip: text and -webkit-text-fill-color: transparent for the gradient to show through text[10].
    • Edge (Chromium-based): Same support as Chrome.
    • Safari (macOS and iOS): Supports the property with the -webkit- prefix[10].
    • Opera (desktop and Android): Same as Chrome, supports the required prefixes[10].
    • Samsung Internet: Built on Chromium, thus also supports these properties[10].
  • Not supported:

    • Firefox: As of July 2025, Firefox does not support background-clip: text (neither standard nor prefixed), making gradient text via this method not possible in Firefox[10]. There is ongoing interest and discussion, but there is no production support[10].
    • Internet Explorer: Not supported and will not be supported as the browser is deprecated.

Syntax for gradient text (for best browser coverage):

.gradient-text {
  background: linear-gradient(to right, hotpink, cyan);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}
  • Standard background-clip: text (without prefix) has experimental or no support; always use the prefixed version for cross-browser coverage[10].

Fallbacks and alternatives:

  • For Firefox and legacy browsers, you may provide solid color text as a fallback or use SVG/text-image workarounds.
  • No purely CSS-based solution for gradient text works in Firefox as of the current date[10].

Key points:

  • Safari, Chrome, Edge, Opera: Use the -webkit- prefix.
  • Firefox: No support as of July 2025.
  • Standardization: Although background-clip: text is part of a spec draft, only WebKit/Blink browsers implement it for text; no confirmed plans for Firefox as of now.

References:

  • The latest guidance from front-end experts and code snippets as of 2025[10].
  • Caniuse and browser documentation indicate no Firefox support for this feature as of mid-2025[10].

Citations:


Add fallback for browsers without gradient-text support

Firefox and Internet Explorer don’t support -webkit-background-clip: text, so you should provide a solid‐color fallback or wrap the gradient styles in a feature query. For example, in home.css around lines 194–197:

β€’ Prepend a fallback color
β€’ Wrap the gradient block in an @supports rule or include both fallback and gradient styles
β€’ Remove the unprefixed background-clip: text; (no production support)

Proposed diff:

 .gradient-text {
+  /* Fallback for non-WebKit browsers */
+  color: var(--text-color);

+  /* Gradient text for WebKit/Blink/Safari */
+  background: linear-gradient(135deg, var(--text-color), var(--highlight-color));
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
-  background-clip: text;
 }

Or using a feature query:

.gradient-text {
  color: var(--text-color);
}

@supports (-webkit-background-clip: text) {
  .gradient-text {
    background: linear-gradient(135deg, var(--text-color), var(--highlight-color));
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
  }
}
πŸ€– Prompt for AI Agents
In home.css around lines 194 to 197, add a solid color fallback by setting the
color property before the gradient styles. Wrap the gradient background,
-webkit-background-clip, and -webkit-text-fill-color properties inside an
@supports rule checking for -webkit-background-clip: text support. Remove the
unprefixed background-clip: text property as it lacks production support. This
ensures browsers without gradient-text support display a solid color fallback.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
script.js (3)

9-29: Consider caching DOM elements and extracting icon toggle logic.

The function is well-implemented with good error handling and fallbacks. The localStorage compatibility check and early return pattern are excellent practices.

Consider this refactor for better performance and maintainability:

function applySavedTheme() {
  const savedTheme = (window.localStorage && window.localStorage.getItem("theme")) || "light";
  const themeToggleBtn = document.getElementById("theme-toggle");
  const moonIcon = document.querySelector(".moon-icon");
  const sunIcon = document.querySelector(".sun-icon");

  if (!themeToggleBtn || !moonIcon || !sunIcon) return;

-  if (savedTheme === "dark") {
-    document.body.classList.add("dark-theme");
-    moonIcon.style.display = "none";
-    sunIcon.style.display = "block";
-  } else {
-    document.body.classList.remove("dark-theme");
-    moonIcon.style.display = "block";
-    sunIcon.style.display = "none";
-  }
+  const isDark = savedTheme === "dark";
+  document.body.classList.toggle("dark-theme", isDark);
+  moonIcon.style.display = isDark ? "none" : "block";
+  sunIcon.style.display = isDark ? "block" : "none";
}

31-64: Extract shared DOM queries and icon toggle logic to reduce duplication.

The theme toggle implementation is robust with excellent error handling and localStorage fallbacks. However, there's code duplication with applySavedTheme() - both functions query the same DOM elements and perform similar icon toggling.

Consider extracting shared logic:

+function getThemeElements() {
+  return {
+    themeToggleBtn: document.getElementById("theme-toggle"),
+    moonIcon: document.querySelector(".moon-icon"),
+    sunIcon: document.querySelector(".sun-icon")
+  };
+}
+
+function toggleThemeIcons(moonIcon, sunIcon, isDark) {
+  moonIcon.style.display = isDark ? "none" : "block";
+  sunIcon.style.display = isDark ? "block" : "none";
+}

function initializeEventListeners() {
-  const themeToggleBtn = document.getElementById("theme-toggle");
-  const moonIcon = document.querySelector(".moon-icon");
-  const sunIcon = document.querySelector(".sun-icon");
+  const { themeToggleBtn, moonIcon, sunIcon } = getThemeElements();

  if (themeToggleBtn && moonIcon && sunIcon) {
    themeToggleBtn.addEventListener("click", () => {
      document.body.classList.toggle("dark-theme");
      const isDark = document.body.classList.contains("dark-theme");
      
      try {
        window.localStorage?.setItem("theme", isDark ? "dark" : "light");
      } catch (e) {
        console.warn("Failed to save theme preference:", e);
      }
      
-      if (document.body.classList.contains("dark-theme")) {
-        try {
-          window.localStorage?.setItem("theme", "dark");
-        } catch (e) {
-          console.warn("Failed to save theme preference:", e);
-        }
-        moonIcon.style.display = "none";
-        sunIcon.style.display = "block";
-      } else {
-        try {
-          window.localStorage?.setItem("theme", "light");
-        } catch (e) {
-          console.warn("Failed to save theme preference:", e);
-        }
-        moonIcon.style.display = "block";
-        sunIcon.style.display = "none";
-      }
+      toggleThemeIcons(moonIcon, sunIcon, isDark);
    });
  }

125-162: Consider more robust placeholder generation.

The form synchronization approach using a mapping array is excellent for maintainability and clarity. The implementation is clean and well-structured.

Consider making the placeholder generation more robust:

function syncInput(inputId, previewId) {
  const input = document.getElementById(inputId);
  const preview = document.getElementById(previewId);
  if (input && preview) {
    input.addEventListener("input", () => {
-      const placeholder = `[${previewId.replace("preview", "").replace("bottom", "")}]`;
+      const fieldName = previewId
+        .replace(/^(preview|bottom)/, "")
+        .replace(/([A-Z])/g, " $1")
+        .toLowerCase()
+        .trim();
+      const placeholder = `[${fieldName}]`;
      preview.innerText = input.value || placeholder;
    });
  }
}

This makes placeholders more readable (e.g., [company name] instead of [CompanyName]).

πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between 6df9a5d and d4f2fab.

πŸ“’ Files selected for processing (2)
  • invoice.html (1 hunks)
  • script.js (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • invoice.html
πŸ”‡ Additional comments (5)
script.js (5)

1-7: LGTM! Well-structured initialization sequence.

The DOMContentLoaded event handler follows a logical order: setting initial values, applying saved theme, and then initializing event listeners. This is a clean and maintainable approach.


65-107: LGTM! Excellent event listener organization and delegation.

The event listener setup demonstrates good practices:

  • Proper null checks before attaching listeners
  • Effective use of event delegation for dynamic elements
  • Clean separation of concerns with helper functions
  • Logical initialization sequence

164-223: LGTM! Excellent row management improvements.

The row management refactoring demonstrates several best practices:

  • Safe parsing with fallbacks in calculateRowTotal()
  • Template-based row creation in addNewRow() (more reliable than cloning existing rows)
  • Proper validation to prevent deletion of the last row
  • Clean separation of concerns across functions

The switch to template cloning is particularly well done - it ensures new rows are always clean and consistent.


225-283: LGTM! Robust preview update with excellent safety checks.

The updatePreview() function demonstrates excellent defensive programming:

  • Proper null checks for required elements
  • Safe parsing with fallbacks for numeric inputs
  • Dynamic tax label updates reflecting user input
  • Consistent currency symbol handling throughout the preview

The implementation handles edge cases well and maintains data integrity.


285-344: LGTM! Comprehensive PDF download implementation with excellent UX.

The downloadPDF() function demonstrates production-ready code with excellent user experience:

  • Proper loading state management with visual feedback
  • Comprehensive error handling with user-friendly alerts
  • Library availability checks to prevent runtime errors
  • Enhanced html2pdf options with CORS support
  • Consistent button state restoration in all scenarios (success, error, unavailable)

The implementation handles edge cases gracefully and provides clear feedback to users throughout the process.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
script.js (3)

19-23: Consider using CSS classes instead of inline styles.

While the current implementation works, consider using CSS classes to toggle icon visibility for better separation of concerns and easier maintenance.

-function toggleThemeIcons(moonIcon, sunIcon, isDark) {
-  moonIcon.style.display = isDark ? "none" : "block";
-  sunIcon.style.display = isDark ? "block" : "none";
-}
+function toggleThemeIcons(moonIcon, sunIcon, isDark) {
+  moonIcon.classList.toggle("hidden", isDark);
+  sunIcon.classList.toggle("hidden", !isDark);
+}

Then add this CSS rule:

.hidden { display: none; }

25-35: Add theme value validation for robustness.

The function handles localStorage access well with fallbacks, but consider validating the saved theme value to prevent unexpected behavior.

 function applySavedTheme() {
-  const savedTheme = (window.localStorage && window.localStorage.getItem("theme")) || "light";
+  const rawTheme = window.localStorage && window.localStorage.getItem("theme");
+  const savedTheme = (rawTheme === "dark" || rawTheme === "light") ? rawTheme : "light";
   const { themeToggleBtn, moonIcon, sunIcon, body } = getThemeElements();

81-91: Consider breaking down the large event listener function.

While the consolidated approach works well, the initializeEventListeners() function is becoming quite large. Consider extracting specific listener groups into separate functions for better maintainability.

 function initializeEventListeners() {
   const { themeToggleBtn, moonIcon, sunIcon, body } = getThemeElements();
-  
-  // Theme toggle logic...
-  // Currency selector logic...
-  // Tax rate logic...
-  // Add row button logic...
-  // Download button logic...
-  // Event delegation...
+  
+  setupThemeToggle(themeToggleBtn, moonIcon, sunIcon, body);
+  setupFormControls();
+  setupEventDelegation();
   
   bindInitialRows();
   setupFormSync();
   updatePreview();
 }
πŸ“œ Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

πŸ“₯ Commits

Reviewing files that changed from the base of the PR and between d4f2fab and edcea8c.

πŸ“’ Files selected for processing (1)
  • script.js (4 hunks)
πŸ”‡ Additional comments (7)
script.js (7)

9-17: LGTM! Clean theme element caching.

The getThemeElements() function provides a clean way to cache DOM references and prevent repeated queries. The destructuring pattern makes the code readable and maintainable.


37-53: Excellent error handling for localStorage operations.

The theme toggle implementation correctly handles localStorage failures and includes proper error logging. The defensive programming approach with null checks prevents runtime errors.


114-157: Excellent refactoring of form synchronization.

The centralized mapping array approach and improved placeholder generation logic are significant improvements. The regular expression for converting camelCase to readable format is well-implemented and handles edge cases properly.


195-207: Great improvement using template-based row cloning.

The switch from cloning existing rows to using a template element is a significant improvement. This ensures clean new rows without inherited data and provides more predictable behavior.


181-193: Robust calculation with proper error handling.

The calculateRowTotal() function properly handles missing inputs and edge cases. The conditional formatting of the total value (showing empty string for zero) provides good UX.


220-278: Comprehensive and robust preview update implementation.

The updatePreview() function handles all edge cases well, includes proper safety checks, and maintains data consistency. The dynamic tax label updates and currency symbol synchronization are particularly well-implemented.


280-335: Excellent enhancement of PDF download functionality.

The improved error handling, user feedback during generation, and enhanced html2pdf options significantly improve reliability. The button state management and CORS support address common PDF generation issues effectively.

@vercel
Copy link

vercel bot commented Aug 24, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
gen-invoice Ready Ready Preview Comment Aug 24, 2025 2:07pm

@versac3s versac3s merged commit 311be7c into versac3s:main Aug 24, 2025
3 checks passed
This was referenced Sep 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants