The text comprises excerpts from a .pdf file detailing the development of an invoicing application using Next.js, React, and various UI component libraries (such as Chakra UI and Lucid React). The author meticulously documents the creation of UI components, including tables, forms, and dropdowns, while implementing server-side and client-side validations with Zod and Form. The process covers building routes for invoice creation and editing, integrating email functionality using Mailtrap, and incorporating data fetching and display from a Prisma database. Finally, the author addresses the creation of a dashboard and landing page for the application, highlighting the transition from development to production deployment.
Project Review: Invoice Management Application
Quiz
- What is the primary purpose of the package.json file in this project?
- The package.json file lists all the dependencies used in the project and their respective versions. It also includes scripts to run different development processes.
- Describe the relationship between layout.tsx and page.tsx in the Next.js app structure.
- The layout.tsx file defines the overall structure of the page, and the page.tsx file represents a specific route within that layout. The layout renders its children, which are the routes.
- Why is TypeScript used in the project, and is it required?
- TypeScript is used to add static typing, which makes the code simpler and easier to maintain, especially in large projects. However, it is not strictly required and the project can be done with JavaScript.
- What is the purpose of the .env file, and what does it contain in this project?
- The .env file stores environment variables that are needed for the application to run. It includes a secret key used by the Auth.js library and the MailTrap token.
- Explain the function of the off.ts file within the utils folder.
- The off.ts file is a configuration file for off.js. It defines the authentication providers, specifies custom authentication logic and the adapter, like Prisma or Magic links.
- What is a “W Handler” in the context of Next.js?
- A “W Handler” is another word for an API endpoint that uses web request and response APIs to handle different requests, for example when signing in or out the user, or fetching data.
- How does the requireUser hook secure routes in this application?
- The requireUser custom hook checks if a user has an active session. If there is no session, the hook redirects to the login page.
- What is the role of the useFormStatus hook and where is it used in this project?
- The useFormStatus hook provides the status information for the latest form submission. In this project, it is used in the submit button component to track the pending state.
- What is the purpose of the MailTrap API token in this application, and how is it used?
- The MailTrap API token is used to authenticate requests to the MailTrap email service. It’s used to send transactional emails such as the invoice reminder emails.
- Describe the primary goal of the PDF generation functionality in this application.
- The PDF generation functionality generates downloadable invoices. This process creates a PDF with invoice details by fetching them from the database.
Essay Questions
- Analyze the architectural decisions made in this project, particularly concerning the separation of client-side and server-side components and the use of custom hooks.
- Discuss the role of third-party libraries (like Auth.js, Shadcn-UI, and jsPDF) in accelerating development and the potential trade-offs of relying on them.
- Examine the implementation of authentication and authorization in the project, including the use of magic links and the protection of routes.
- Evaluate the user experience design of the application, considering aspects like the login process, onboarding flow, and invoice management.
- Describe the process of sending reminder emails and generating PDFs. Include the different tools and steps and how they integrate into the application.
Glossary
- pnpm: A package manager similar to npm but known for being faster and more efficient.
- TypeScript: A superset of JavaScript that adds static typing.
- ESLint: A tool for identifying and reporting on patterns found in ECMAScript/JavaScript code.
- TND: An abbreviation that refers to Tailwind CSS, a utility-first CSS framework.
- App Router: A feature of Next.js that allows you to structure your application using a directory based routing system.
- Turbo Pack: A high-performance build system optimized for web development, often used with Next.js.
- vs code: A popular code editor.
- TS config: A configuration file for TypeScript.
- package.json: A file that lists dependencies, scripts, and other metadata for a Node.js project.
- React: A JavaScript library for building user interfaces.
- NextJS: A React framework for building web applications with features like server-side rendering.
- deps: Project dependencies, such as libraries or packages that are required for it to function.
- g ignore file: A file that specifies intentionally untracked files that Git should ignore.
- EnV: A file used to store environment variables, like sensitive information such as API keys.
- Def server: A local development server, often used during development of web applications.
- Off JS: An authentication library for web applications.
- Magic Links: An authentication method where users click a link sent to their email address.
- Radex UI: a UI component library used to speed up the development process with pre-made styled components.
- W Handler: An API route or endpoint that uses web request and response APIs.
- Prisma: A database toolkit that provides an ORM (Object-Relational Mapper).
- use client: A directive used to indicate that a component should be rendered on the client-side.
- useFormStatus: A React hook that provides information about the latest form submission status.
- Lucid react: A library providing icons for web applications.
- International API: a JavaScript API used for formatting dates, numbers, and currency according to locale-specific conventions.
- NodeJS: A runtime environment for executing JavaScript on the server-side.
- jspdf: A client-side JavaScript library for generating PDFs.
- MailTrap: A service for email testing and sending with API integration.
- Sona: A library used for notifications, also known as toast messages, in the front end.
- fetch: An API used for making network requests.
- UI.shat cn.com: The website for a popular UI library which provides components.
- Recharts: A charting library for React applications.
- Cartesian Grid: A grid used to create a space for data visualization, such as a chart.
Invoice Management Application Development
Okay, here’s a detailed briefing document summarizing the provided source, with quotes included where relevant:
Briefing Document: Invoice Management Application Development
Document Overview: This document reviews a series of transcripts detailing the development of an invoice management application using Next.js, TypeScript, and various libraries. The excerpts cover project setup, authentication implementation, UI component creation, email integration, PDF generation, data visualization, and the deployment process.
I. Project Setup and Core Technologies
- pnpm for Package Management: The developer uses pnpm for project creation, highlighting its differences from npm.
- “here let me do a pnpm create and then widespace next Das app at latest so this is how you bootstrap a project with pnpm it’s a bit different than if you would use npm…”
- Next.js as the Framework: The application is built on the Next.js framework, leveraging its features such as the app router and server components.
- TypeScript for Type Safety: TypeScript is used to enhance code maintainability and reduce bugs. While not mandatory, it’s suggested.
- “I use typescript it isn’t required you can use JavaScript that’s fine but typescript makes your life a bit simpler easier…”
- Tailwind CSS for Styling: Tailwind CSS (referred to as “tnd”) is used to style the application. A tailwind.config.js file is part of the setup.
- Project Structure:app folder: Contains most of the core application logic.
- page.tsx: Index page.
- layout.tsx: Application layout.
- api: For API routes.
- dashboard: Features dashboard-related routes.
- invoices: Folder for invoice routes.
- public: Static assets.
- utils: Utility functions and configuration.
- components: Custom and shared UI components.
II. Authentication with Auth.js
- Auth.js Implementation: The application uses Auth.js for handling user authentication.
- “for authentication as you all know there are a lot of options on the market but we will use off JS…”
- Magic Links: The authentication method is magic links, where users enter their email, and receive a login link.
- “in off JS or in combination with off JS we will use magic links this is the method we will use to authenticate the user…”
- Environment Variables: An AUTH_SECRET environment variable is crucial for Auth.js to encrypt tokens and verification hashes.
- “this means we have to add a environment vable which is the off secret this is a random value used by the library to enp tokens…”
- API Route Handler: An API route handler /api/auth/[…nextauth]/route.ts is created to manage authentication API endpoints.
III. UI Component Development
- Custom Components: The developer creates custom components within a separate components directory to distinguish between shared and custom components.
- Shadcn/UI Integration: The project integrates components from shadcn/ui for a consistent and styled user interface. Many components are installed, including card, label, input, button, select, textarea, calendar, and popover.
- Login Form: A login form is built using card, label, input, and button components.
- “…I want to now render my card uh content and in the card content I want to render my label the input and then also our submit button…”
- Pending States: The useFormStatus hook is used to display pending states on form submissions.
- “to show the pending State for the user we will have to use a hook which is called use form status this is a hook provided by react…”
- Custom Submit Button: A custom SubmitButton component is created to manage loading states.
IV. Email Integration with Mailtrap
- Mailtrap SDK: Mailtrap’s Node.js SDK is used to send transactional emails.
- “this is a relatively new feature with mail trap we have a mail trap client which we can now also Implement into our application and then we don’t have to use SMTP anymore…”
- API Token: The Mailtrap API token is stored in an environment variable (MAILTRAP_TOKEN).
- Email Templates: A no-code UI builder is used to create email templates. In this specific case, a “reminder email” template is used.
- Email Sending Logic: An email is sent after an invoice is created.
- “once the user creates an invoice I want to send a email and that’s what we will do inside of here…”
- Email Template: The mailtrap HTML UI builder is utilized to craft a visually appealing reminder email.
V. PDF Generation with jsPDF
- jsPDF Library: jsPDF library is used to generate PDF documents on the server side.
- PDF Document Setup: The PDF is configured with orientation, unit (millimeters), and format (A4).
- “let’s initialize JS PDF so let me do a constant PDF or you could call it DOC but I think PDF is a bit more uh what would you say explanatory if this makes sense and then this is equal to new jspdf…”
- Dynamic Data Rendering: Data from the invoice is dynamically used to populate the PDF. This includes invoice details, sender and receiver information, and item descriptions.
- Custom Layout: The PDF layout is customized with font sizes, text positioning, and lines.
- Content Disposition: The PDF is returned with a header indicating inline display.
VI. Data Visualization
- Recharts Library: Recharts, integrated through Shadcn/UI, is used to create a chart within the dashboard.
- Graph Component: A separate graph component is made which utilizes a JavaScript bundle and is marked as use client. This component displays a line chart representing paid invoices over the past 30 days.
- Data Preparation: The graph data is dynamically fetched and passed to the recharts components.
VII. Other Important Implementation Details
- Server Actions: Server actions were utilized for form handling and data modification.
- Custom Hooks: A custom requireUser hook was created to check if the user is authenticated for protected routes and a custom formatCurrency function was created to ensure consistency when displaying monetary values.
- Toasts: Sonner library is used to display toast notifications when there is a success or failure of actions.
- Empty State: A custom EmptyState component is displayed when no invoices are present on the dashboard.
- Dynamic Routes: Dynamic routes such as dashboard/invoices/[invoiceId] are used to handle individual invoice pages.
- Suspense Boundaries: Suspense boundaries are added for asynchronous components to improve user experience while data is loading.
VIII. Key Quotes and Takeaways
- Focus on UI Consistency: The developer emphasizes importing components from the custom components folder rather than directly from shadcn/ui to avoid errors.
- “please make sure that you import all of your components from the components folder please don’t import it from radex UI if you import it from redex UI you will get a lot of errors and you don’t want that…”
- Code Organization: Importance was placed on a clean architecture, utilizing a utils folder, separate component folders for different component types, and a custom hooks file for reusable logic.
- Importance of Error Handling: There is a consistent implementation of try-catch blocks to gracefully handle errors and display user-friendly messages.
- Data validation: There is a consistent validation of data to ensure data integrity. This includes id validation, user authorization, and checks for optional values.
IX. Next Steps
- Landing Page: The final step before deployment is creating a landing page.
- Deployment: The application is prepared for deployment.
Conclusion: The transcript highlights a detailed development process for an invoice management application using a variety of modern web technologies. It emphasizes the importance of code organization, user experience, error handling, and consistent UI. This briefing document should serve as a comprehensive overview of the development process.
Building a Next.js App with pnpm and Auth.js
1. What is pnpm and how does it differ from npm when creating a new project?
pnpm (Performant npm) is a package manager that is similar to npm (Node Package Manager), but with differences in how it creates projects. When using pnpm, you would use pnpm create followed by the desired project template (in this case, widespace next), while npm uses npm create followed by the project template. Pnpm is known for its efficient disk space usage and faster install times.
2. Why is TypeScript used in this project, and is it required?
While not strictly required, TypeScript is used in this project to make development simpler and easier by providing static typing to JavaScript. TypeScript makes it easier to catch errors and maintain the codebase. However, JavaScript is also a viable option if you are not familiar with TypeScript. The project can be followed without any prior Typescript knowledge.
3. Can you explain the folder structure of this Next.js project?
The project structure includes the following key folders and files:
- tsconfig.json: Configuration file for TypeScript.
- twin.config.js: Configuration file for Tailwind CSS (tnd).
- package.json: Contains project dependencies (e.g., React, Next.js) and scripts.
- next.config.js: Configuration file for Next.js settings, including image whitelisting.
- .gitignore: Specifies files and directories to ignore in Git.
- public/: Stores static files like images and videos.
- app/: The most important folder containing application routes and layouts.
- page.tsx: The index page of the application.
- layout.tsx: The main layout component that wraps all routes.
- globals.css: Stores CSS variables.
- fonts/: For storing custom fonts.
- api/: Contains API routes, including the authentication route (/api/auth/[…nextauth]/route.ts).
- utils/: Contains utility functions and custom hooks.
- components/: Contains reusable UI components.
4. How does the layout component work in Next.js, and how is it connected to pages?
In Next.js, the layout component, typically layout.tsx, wraps the content of all pages within the app folder. The layout renders its defined elements and then inserts the content of the current page as children via children. This means that elements rendered in the layout are persistent across all routes unless specified otherwise.
5. What is Auth.js and why is it used in this project?
Auth.js is an open-source authentication library used to implement authentication for web applications. It provides an easy way to add authentication with various methods. In this project, it’s used with magic links, where users enter their email, receive a link, and are then redirected back to the application, thus validating them as the owner of the email.
6. How is user authentication handled in this application and what is a magic link?
User authentication is handled using Auth.js in combination with magic links. A user enters their email address, and the application sends an email to that address containing a unique link. The user clicks the link, and upon returning to the application, their session is established. Magic links provide a passwordless method of authentication.
7. How is the dashboard route protected and what is the requireUser hook?
The dashboard route is protected by a custom hook called requireUser. This hook checks if a valid user session exists. If no valid session is found, it redirects the user to the login page. The hook is used on server components to ensure that unauthorized users cannot access secured routes. The requireUser hook encapsulates the logic to check if a user is authenticated and handles the redirection if a user is not.
8. How is PDF generation implemented and what libraries are used?
PDF generation is implemented using the jsPDF library. The library is used to create a PDF document programmatically, adding text, lines, and formatted data. Once the PDF document is created, it’s converted into a buffer and returned as a downloadable file (or displayed inline in this example) via the HTTP response.
Card UI Component Implementations
The sources describe various implementations of Card UI components, often using a combination of custom components and styling utilities, particularly from Shadcn UI. These cards are used to structure content, provide visual separation, and create interactive elements in web applications.
Key aspects of card UI in the sources include:
- Structure:
- Cards are often built using a card component as a base, which may include a card header, card content, and card footer.
- The card header typically contains titles, descriptions, and icons.
- The card content houses the primary content of the card, such as forms, tables, or images.
- The card footer often contains buttons or links for interaction.
- Layout and Styling:
- Cards use flexbox and grid layouts for positioning elements.
- Classes such as flex, flex-col, items-center, justify-center, grid, and grid-cols-* are used for layout.
- Spacing is controlled using utility classes like gap-*, m-*, p-*, and space-y-*.
- Cards are given a maximum width using max-w-* and are centered with mx-auto.
- Background colors, borders, and rounded corners are added using classes like bg-*, border, and rounded-*.
- Text styling includes classes for size (text-*), weight (font-*), color (text-*), and alignment (text-center).
- Custom widths can be set using array brackets, for example, w-[380px].
- Components:
- Custom components such as Card, CardHeader, CardContent, CardTitle, CardDescription, and CardFooter are used.
- These components are styled using utility classes from libraries like Shadcn UI.
- Buttons within cards are often styled using the buttonVariants method to maintain consistency.
- Icons from libraries like Lucid React are integrated within card components using components such as MailIcon, AlertCircle, ArrowLeft, Pencil, DownloadCloud, Trash, CheckCircle, DollarSign, and Users.
- Forms and inputs are created within cards, including labels, text areas, and select elements.
- Images and GIFs are also incorporated into the card.
- Specific Implementations:
- Login Form: Uses a card to contain a form with labels, inputs, and a submit button.
- Verification Page: Uses a card with an icon, title, and description to indicate email verification.
- Invoice List: Displays a card with a title, description, and a table of invoices.
- Invoice Creation Form: Uses a card to contain a multi-input form for creating new invoices.
- Delete Invoice Confirmation: Shows a card with a warning message and confirmation buttons.
- Mark Invoice as Paid Confirmation: Displays a card with a confirmation message and buttons to mark the invoice as paid.
- Dashboard Blocks: Uses multiple cards in a grid layout to display key metrics and data.
- Invoice Graph: Renders a card containing a chart to visualize invoice data.
- Responsiveness:
- Cards are designed to be responsive using grid layouts and media queries, like md: and lg: prefixes in class names.
- Cards may use a maximum width, such as max-w-sm, to limit their size on larger screens.
- The layout of card content may change based on screen size, for example using grid-cols-2 or grid-cols-3.
- Interactivity:
- Cards include interactive elements like links and buttons, often styled with the buttonVariants method.
- Some cards have popovers or dropdown menus for additional actions or information.
- Cards are frequently integrated with server actions to perform actions such as submitting forms, deleting invoices, and marking invoices as paid.
- Theming:
- Cards use CSS variables provided by Shadcn UI for consistent styling.
- Color palettes are defined in CSS and used within utility classes such as bg-muted, text-muted-foreground, and bg-primary.
- Custom colors and gradients are also implemented.
In summary, the card UI implementations in the sources are built using a combination of flexible layout techniques, custom components, styling utilities from Shadcn UI, and interactive elements. They are designed to be responsive and maintain a consistent look across the application.
Shadcn UI Button Styling Guide
The sources provide several examples of button styling, primarily using the buttonVariants method from Shadcn UI, along with other utility classes to achieve specific looks. The goal is to create consistent, accessible, and visually appealing buttons that enhance user interaction.
Key aspects of button styling include:
- buttonVariants method:
- This method is used to apply a consistent set of styles to button elements, whether they are <button> elements or <a> elements styled to look like buttons.
- It is imported from the components folder and invoked with an object that specifies style variations.
- The method allows for dynamic styling through variants and class names.
- Variants:
- The variant property is a key aspect of button styling using buttonVariants.
- Common variants include outline, secondary, ghost, and destructive.
- The outline variant creates a button with a border and transparent background.
- The secondary variant provides a button with a muted background color.
- The destructive variant is used to highlight potentially dangerous actions and often uses a red background color.
- If no variant is provided, the default style is applied.
- Class names:
- The class name property is used to add additional styling, including width, margin, and other CSS properties.
- For example, w-full makes the button take the full width of its container.
- Other classes include rounded-full for rounded corners, and text-left for aligning text to the left.
- Button components:
- Buttons are typically rendered using the <button> component from the components folder or are stylized <a> elements using the <Link> component from next/link.
- The asChild property is used to prevent the error of a button being a descendant of a button when using the Link component.
- Icons:
- Icons from libraries like Lucid React are integrated within button elements to enhance their visual appeal.
- Icons are given class names for sizing (size-*) and spacing (mr-*, ml-*).
- Dynamic Text:
- Button text can be passed as a dynamic property, allowing for the text to be changed without creating a new component.
- Styling links as buttons:
- The buttonVariants method is used to style the Link component from next/link to look like buttons, which allows for navigation while maintaining a consistent button style.
- Accessibility:
- The button styles provided by Shadcn UI are designed to be accessible, with appropriate contrast and focus states.
- Submit Buttons:The submit button component is designed to handle form submission and has a pending state with a spinner.
- The text property renders dynamic text for the submit button, and the variant property allows for different styling variations.
In summary, button styling in the sources is achieved through a combination of the buttonVariants method, utility classes, and careful integration of icons and text. This approach allows for creating visually appealing and functional buttons that provide a consistent user experience across the application, which enables styling buttons with various backgrounds, borders, text alignment, and interactive feedback.
Shadcn UI Table Rendering
The sources describe a comprehensive approach to rendering tables, primarily within the context of displaying invoice data, using a combination of custom components and styling utilities from Shadcn UI. The process involves creating a responsive and visually appealing table that can handle dynamic data and user interactions.
Key aspects of table rendering include:
- Structure:
- A table component serves as the wrapper for the entire table structure.
- The table is divided into a table header and a table body, each with distinct roles.
- The table header contains the column labels, rendered using table row and table head components.
- The table body houses the actual data rows, rendered with table row and table cell components.
- Components:
- Custom components like Table, TableHeader, TableRow, TableHead, TableBody, and TableCell are used to construct the table.
- These components are styled using utility classes from libraries like Shadcn UI, ensuring a consistent look and feel.
- The table header uses table head elements to define column labels, and the table body renders rows using table cell elements to display data values.
- Layout and Styling:
- The table is made responsive using flexbox and grid layouts.
- Classes such as flex, flex-col, items-center, justify-center are used for positioning.
- Spacing is managed using classes like gap-*, m-*, p-*.
- Text alignment is controlled with classes like text-left and text-right.
- Custom widths can be set using array brackets, for example w-[100px].
- The table uses CSS variables provided by Shadcn UI for consistent styling.
- Dynamic Data:
- Tables are designed to display dynamic data fetched from a database or an API.
- The data is typically mapped over to create table rows using the map function.
- Each data item corresponds to a row, and each property of a data item populates the table cells within that row.
- The key prop is used to uniquely identify each row when mapping over data.
- Table Header:
- The table header uses the table head component which serves as labels for the data below, for example, “invoice ID,” “customer,” “amount,” “status,” “date,” and “actions”.
- Table head elements can be styled individually, for example with text-right, to control alignment.
- Table Body:
- The table body renders rows of data with table cell elements.
- Each table cell contains a value from the fetched data, corresponding to the column it is in.
- The content of table cells is rendered dynamically, often with the help of helper functions, for example to format a date, or format currency.
- Actions Column:
- The “actions” column often includes a dropdown menu for interactions with each row.
- The dropdown is rendered with the DropdownMenu, DropdownMenuTrigger, and DropdownMenuContent components from Shadcn UI.
- The dropdown menu items are links styled to look like buttons with the buttonVariants method.
- These dropdown menus may contain interactive elements such as “edit invoice”, “download invoice”, “send reminder email”, “delete invoice”, and “mark as paid”.
- The alignment of the dropdown menu content is controlled using the align property of DropdownMenuContent.
- Responsiveness:
- Tables are designed to be responsive and adapt to different screen sizes.
- Layout changes, such as column widths, are often managed using media queries.
- Integration with other components:
- Tables are frequently integrated with other components such as cards and popovers to provide a structured user interface.
- They are often used within card components to display data within a container.
- Conditional Rendering
- Tables can be rendered conditionally based on data availability. An empty state component can be rendered if there is no data.
- A fallback can be rendered when loading table data, for example with the Suspense component.
- Dropdown menu items can be conditionally rendered, for example, the “Mark as paid” item is only shown when the invoice is not already marked as paid.
In summary, table rendering in the sources is achieved through the use of a flexible and modular structure with custom components, styling utilities from Shadcn UI, and dynamic data mapping. The resulting tables are responsive, visually appealing, and integrate well with the other UI components of the application, providing users with a clear view of their data and the ability to interact with it.
Client-Side Validation with Conform and Zod
Client-side validation is implemented in the sources using the Conform library in conjunction with Zod. This approach ensures that form data is validated on the client side before submission, providing a better user experience with immediate feedback, and also ensures that the data is safe to store in the database.
Here’s a breakdown of how client-side validation is handled:
- Zod for Schema Definition:
- Zod is used to define the schema for form data. This involves specifying the types of fields (e.g., string, number, email) and any additional constraints (e.g., minimum length, required).
- For example, a schema can specify that a “first name” field must be a string with a minimum length of two characters, and it can provide a custom error message if this rule isn’t met.
- Schemas are defined in a separate file, for example, zortSchemas.ts.
- The schemas are then imported in the components where the forms are rendered.
- Conform for Validation:
- Conform is used to validate form data against the Zod schema, on both the client side and the server side.
- The useForm hook from Conform is used to manage form state and validation. This hook is initialized with the last result from the server action, to keep the client and server state in sync.
- The useForm hook takes a validate callback that performs the actual validation using the passWithZod function.
- The passWithZod function compares the form data against the Zod schema and returns any errors.
- passWithZod Function:
- The passWithZod function is imported from @conform/zod and is used to compare form data against the Zod schema.
- It takes the form data and the Zod schema as arguments and returns a submission object that contains the validation result, including any errors.
- useActionState Hook for Server Communication:
- The useActionState hook from React is used to handle server actions and to get responses from server actions.
- It takes the server action and an initial state as arguments. It returns the last result from the server action and the server action itself. This hook is used to make a connection between the client side and server side, so that if there are server-side errors, the client can render the errors below the input fields.
- Form Setup:
- The form element is connected to Conform using the form.id and form.onSubmit properties that are returned from the useForm hook.
- The noValidate property is set on the form to prevent the browser’s default validation.
- Input Field Integration:
- Input fields are connected to Conform using the fields object returned from the useForm hook.
- Each input field uses fields.[fieldName].name, fields.[fieldName].key and fields.[fieldName].defaultValue.
- Error Display:
- Errors are displayed using fields.[fieldName].errors. This displays any errors returned by the validation process.
- Error messages are typically styled with a small red font.
- Validation Triggers:
- The shouldValidate property in the useForm hook is set to onBlur, which means the form is validated when an input loses focus.
- The shouldRevalidate property is set to onInput, which means the form is revalidated whenever the value of an input changes. This provides real-time validation as the user types.
- Reusing Schemas:
- The same Zod schemas are used for both client-side and server-side validation, ensuring consistency between the two. This reduces the risk of discrepancies in validation logic.
In summary, client-side validation in the sources utilizes Conform and Zod to provide robust, type-safe, and user-friendly form handling. This approach not only enhances the user experience by providing immediate feedback on errors but also ensures data integrity before it’s submitted to the server.
Invoice Creation Process
Invoice creation, as described in the sources, is a complex process involving multiple steps, from designing the user interface to implementing server-side logic for data storage and email notifications. The process is designed to be user-friendly, with a focus on real-time validation and a seamless user experience.
Here’s a detailed breakdown of invoice creation:
- User Interface (UI) Design:
- The invoice creation form is built using a combination of custom React components and styling from Shadcn UI.
- The form is divided into sections, each with relevant input fields, for example, a “from” section, a “client” section, a “date and due date” section and an “invoice item” section.
- Input Fields: The form includes various input fields for capturing invoice details, including:
- Text inputs for names, email addresses, addresses, invoice numbers, and descriptions.
- A date picker component for selecting the invoice date.
- A select input for choosing the due date (e.g., net 0, net 15, or net 30).
- Number inputs for quantity and rate of invoice items.
- A text area for adding a note.
- A currency selector.
- The form is structured using grid layouts to create a responsive design, adapting to different screen sizes.
- The form is styled with utility classes from Shadcn UI, for example card, input, label and button to maintain a consistent look and feel.
- Each input is linked to a Conform field, for data management and for client-side validation.
- Client-Side Validation:
- Client-side validation is implemented using the Conform library and Zod.
- Zod is used to define the schema for the invoice data. This schema specifies data types and constraints, such as required fields, minimum lengths, and valid email formats.
- The useForm hook from Conform manages form state and performs validation against the Zod schema using the passWithZod function.
- Real-time validation is triggered on blur and input changes with shouldValidate and shouldRevalidate properties in useForm, providing immediate feedback to the user.
- Errors from validation are displayed below each input field with the fields.[fieldName].errors property.
- Server-Side Action and Data Handling:
- A server action is defined to handle the form submission. This action is marked with the use server directive, indicating it will run on the server.
- The server action uses the same Zod schema for server-side validation, ensuring consistent validation logic.
- The server action first validates the data against the Zod schema using the passWithZod function. If validation fails, error messages are returned to the client.
- If validation is successful, the server action proceeds to create a new invoice record in the database using Prisma.
- Prisma is used as the ORM to interact with the database. The data is stored in the invoice model, which includes fields for all the invoice details.
- The invoice model also includes relations to the user model, allowing for tracking which user created a particular invoice.
- The server action returns a new invoice id, so the user can be redirected to the correct page.
- Email Notifications:
- After creating the invoice, an email is sent to the client.
- Mailtrap is used to send emails. The application uses the Mailtrap SDK, which is easier to implement than a generic node mailer.
- Email templates are created using Mailtrap’s HTML Builder with dynamic data rendering.
- The server action sends a custom email with the invoice details, using the created template.
- The email includes the invoice number, due date, total amount, and a link to download the invoice PDF.
- The email also includes the name of the client, so that the email is personalized.
- PDF Generation:
- A PDF document is generated from scratch using the jspdf library.
- The PDF generation process is initiated via a route handler that fetches the invoice data from the database and converts the invoice details to PDF format, enabling users to download it as a real PDF file rather than just a screenshot.
- The PDF includes key details such as the invoice number, the names of the sender and recipient, as well as the items, quantity, rate and total.
- Integration with Other Components:
- The invoice creation form is integrated into the main dashboard of the application.
- The form uses other components such as cards and popovers, to keep the layout clear and organized.
- The invoice creation form fetches the user information, including the name and address from the database, using the user id from the session.
- Error Handling:
- Both client-side and server-side validation provide error messages when form data is invalid.
- Errors are displayed next to the corresponding input fields, giving the user an idea of what needs to be corrected.
In summary, the invoice creation process is a carefully orchestrated flow involving form rendering, real-time validation, server-side logic, database interaction, and email notifications. It ensures data integrity, provides a smooth user experience, and delivers professional-looking invoices.

By Amjad Izhar
Contact: amjad.izhar@gmail.com
https://amjadizhar.blog
Affiliate Disclosure: This blog may contain affiliate links, which means I may earn a small commission if you click on the link and make a purchase. This comes at no additional cost to you. I only recommend products or services that I believe will add value to my readers. Your support helps keep this blog running and allows me to continue providing you with quality content. Thank you for your support!

Leave a comment