Through a mutual friend, I was introduced to a client who needed a website to showcase their car inventory. I worked closely with them to design and develop a site that not only displays the cars but also provides detailed information, including service history, technical specifications, and other essential details. The project allowed me to combine my technical skills with a user-friendly layout to create an intuitive platform for customers to browse and learn more about the cars on offer.
This image displays the React code handling form submission using the useState hook to manage form fields and an asynchronous fetch function to send data to the server. The form captures user input such as first name, last name, phone, email, and message, and sends it via a POST request. The form also implements error handling and a loading state to manage submission status.
This image shows the Mongoose schema definition for storing contact form data in a MongoDB database. The schema includes fields for first name, last name, email, phone, message, and date. Each field is typed, and the 'date' field is automatically set to the current date by default. This schema is used to define and model the structure of contact form entries in the database.
This image displays the server-side code for handling contact form submissions using MongoDB and Resend API in a Next.js application. The code saves user data to the database using the Contact model and sends an automated response email via the Resend API. It also includes a safeguard to prevent multiple form submissions by setting a flag, ensuring that each form is only processed once. If an error occurs during submission, an error response is returned.
This image shows the React component used to generate a personalized HTML email template using the Resend API. The component dynamically inserts the user's first and last name into the email body and includes a thank-you message, informing the recipient that their message has been received and they can expect a reply within 24 hours. The email is styled with Tailwind CSS, ensuring a clean and responsive design.
This code defines a schema for a 'Car' document used to store car listings in a database. The schema includes fields for car attributes such as model, make, type, year, transmission, price, mileage, engine size, number of previous owners, doors, ULEZ rating, fuel type, and images. The make, year, and other fields provide options lists for predefined values. The schema also generates a slug for each car entry based on the make, model, year, and mileage, which can be used as a unique identifier for each car listing in the app. Additionally, it uses a preview configuration to display a preview title of the car in the format 'Make Model Year'.
This schema defines a 'History' document to track the history of a car, such as past sales or service events. The schema includes a reference to the associated car, using the car field to link to a specific car document. It also includes fields for the date of the event, the dealership involved, a descriptive text field for additional information, and the mileage at the time of the event. The date field is formatted as 'DD-MM-YYYY' for consistency. This schema helps store and retrieve historical data related to each car.
This image displays TypeScript type definitions and a data fetching function used to retrieve car information from a content management system (CMS). The Car type defines the structure of each car object, including properties such as model, year, transmission, price, mileage, and associated image URLs. The getData function executes a GROQ query to fetch the first five car documents, retrieving specific fields like make, model, year, and images. The function formats the data for easy rendering in the application, allowing access to both a primary image (imageUrl) and an array of images (imageArr).
This image shows the server-side code for handling dynamic routing in a Next.js application. The function retrieves car data by calling the getData function and uses the slug parameter from the URL to find a specific car entry. If the car with the corresponding slug is found, it renders the page; otherwise, it returns a loading component. This approach ensures that each car has a unique route based on its slug, allowing for dynamic content generation and efficient data handling in the application.
This image shows the MongoDB collection where contact form submissions are stored. Each document in the collection contains fields such as first name, last name, email, phone, message, and the date the form was submitted. The data is saved using the defined Mongoose schema, ensuring that all user submissions are properly structured and easily retrievable for further processing or review.
This image displays the React component responsible for generating and sending personalized emails in the Car Viewer App. The component uses the Resend API to dynamically populate the email content with the recipient's first and last name. Styled using Tailwind CSS, the email includes a thank-you message confirming receipt of the user's message and provides details about the expected response time. The component demonstrates the integration of React, Resend API, and Tailwind to create responsive and customized email templates.
This image shows the React contact form component that captures user input such as first name, last name, email, phone number, and message. It uses useState to manage the form's state and handle input changes. Upon form submission, the component sends the data to a server via an async function and displays feedback to the user. The component is designed to ensure smooth form submission with proper validation and error handling, providing a seamless user experience.
This image displays the Sanity Studio interface used for managing and editing content in the Car Viewer App. Sanity Studio provides a user-friendly CMS where car listings can be created, updated, and organized. The interface allows you to input various details about each car, such as make, model, year, price, and more. It also supports uploading images and generating slugs for dynamic routing. This setup makes it easy to manage car data in a structured and visually intuitive environment.
Working on this project has helped me develop the following skills:
Ideas I have for expanding and improving this project in the future: