A modern, responsive car wash booking platform built with React, TypeScript, and TanStack Router. This application provides customers with an intuitive interface to book mobile or location-based car wash services.
- π Mobile Service Booking - Professional car wash at your location
- π Location-Based Services - Find and book at nearby car wash facilities
- π Fleet Management - Manage multiple vehicles in your account
- π³ Payment Integration - Secure payment processing with Paystack
- π± Responsive Design - Optimized for desktop, tablet, and mobile devices
- π Real-time Updates - Live booking status and notifications
- β Reviews & Ratings - Service quality feedback system
- π¬ AI Chatbot - Intelligent customer support
- Node.js (v18 or later)
- npm or pnpm package manager
- Clone the repository:
git clone https://github.com/Titus-waititu/CarWash-Client.git
cd CarWash-Client- Install dependencies:
npm install
# or
pnpm install- Start the development server:
npm run dev
# or
pnpm dev- Open http://localhost:3000 in your browser
To build this application for production:
npm run build
# or
pnpm buildThis project uses Vitest for testing. You can run the tests with:
npm run test
# or
pnpm testThis project uses Tailwind CSS for styling with custom components built using shadcn/ui.
This project uses ESLint and Prettier for code quality and formatting. ESLint is configured using tanstack/eslint-config.
npm run lint # Check for linting errors
npm run format # Format code with Prettier
npm run check # Run both linting and formatting checksAdd components using shadcn/ui:
npx shadcn@latest add button
npx shadcn@latest add card
npx shadcn@latest add dialogThis project uses TanStack Router with file-based routing and modular component architecture.
- Modular Booking Flow - Multi-step booking process with reusable components
- Location Services - GPS-based location detection and nearby facility finder
- Mobile Service Support - Complete mobile car wash booking system
- Fleet Management - Multi-vehicle support for users
- Payment Integration - Secure payment processing with multiple providers
The booking system is built with modular step components for better maintainability:
src/components/user/booking-steps/
βββ LocationStep.tsx # Location & mobile service selection
βββ ServiceStep.tsx # Service selection with filtering
βββ VehicleStep.tsx # Vehicle selection from fleet
βββ DetailsStep.tsx # Booking details & summary
βββ BookingSuccessStep.tsx # Confirmation screen
The application integrates with Paystack for secure payment processing:
- Multiple Payment Methods - Card, mobile money, bank transfer
- Secure Processing - PCI compliant payment handling
- Real-time Verification - Instant payment confirmation
- Booking Integration - Seamless booking-to-payment flow
- Intelligent Chatbot - 24/7 customer support with natural language processing
- Smart Recommendations - Personalized service suggestions
- Automated Scheduling - Optimal time slot recommendations
- JWT Authentication - Secure token-based authentication
- Role-based Access - Customer, admin, and vendor roles
- Data Protection - Encrypted sensitive information
- Session Management - Automatic token refresh
Built with mobile-first approach:
- Progressive Web App (PWA) capabilities
- Touch-friendly Interface - Optimized for mobile interactions
- Offline Support - Basic functionality works offline
- Cross-platform - Works on iOS, Android, and desktop
- Code Splitting - Lazy loading for optimal performance
- Image Optimization - Responsive images with lazy loading
- Caching Strategy - Smart caching for better user experience
- Bundle Analysis - Optimized bundle sizes
- User Analytics - Track user behavior and booking patterns
- Performance Monitoring - Real-time performance metrics
- Error Tracking - Comprehensive error reporting
- A/B Testing - Feature testing capabilities
This project uses TanStack Router. The initial setup is a file based router. Which means that the routes are managed as files in src/routes.
To add a new route to your application just add another a new file in the ./src/routes directory.
TanStack will automatically generate the content of the route file for you.
Now that you have two routes you can use a Link component to navigate between them.
To use SPA (Single Page Application) navigation you will need to import the Link component from @tanstack/react-router.
import { Link } from '@tanstack/react-router'Then anywhere in your JSX you can use it like so:
<Link to="/about">About</Link>This will create a link that will navigate to the /about route.
More information on the Link component can be found in the Link documentation.
In the File Based Routing setup the layout is located in src/routes/__root.tsx. Anything you add to the root route will appear in all the routes. The route content will appear in the JSX where you use the <Outlet /> component.
Here is an example layout that includes a header:
import { Outlet, createRootRoute } from '@tanstack/react-router'
import { TanStackRouterDevtools } from '@tanstack/react-router-devtools'
import { Link } from '@tanstack/react-router'
export const Route = createRootRoute({
component: () => (
<>
<header>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</nav>
</header>
<Outlet />
<TanStackRouterDevtools />
</>
),
})The <TanStackRouterDevtools /> component is not required so you can remove it if you don't want it in your layout.
More information on layouts can be found in the Layouts documentation.
There are multiple ways to fetch data in your application. You can use TanStack Query to fetch data from a server. But you can also use the loader functionality built into TanStack Router to load the data for a route before it's rendered.
For example:
const peopleRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/people',
loader: async () => {
const response = await fetch('https://swapi.dev/api/people')
return response.json() as Promise<{
results: {
name: string
}[]
}>
},
component: () => {
const data = peopleRoute.useLoaderData()
return (
<ul>
{data.results.map((person) => (
<li key={person.name}>{person.name}</li>
))}
</ul>
)
},
})Loaders simplify your data fetching logic dramatically. Check out more information in the Loader documentation.
React-Query is an excellent addition or alternative to route loading and integrating it into you application is a breeze.
First add your dependencies:
npm install @tanstack/react-query @tanstack/react-query-devtoolsNext we'll need to create a query client and provider. We recommend putting those in main.tsx.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
// ...
const queryClient = new QueryClient()
// ...
if (!rootElement.innerHTML) {
const root = ReactDOM.createRoot(rootElement)
root.render(
<QueryClientProvider client={queryClient}>
<RouterProvider router={router} />
</QueryClientProvider>,
)
}You can also add TanStack Query Devtools to the root route (optional).
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
const rootRoute = createRootRoute({
component: () => (
<>
<Outlet />
<ReactQueryDevtools buttonPosition="top-right" />
<TanStackRouterDevtools />
</>
),
})Now you can use useQuery to fetch your data.
import { useQuery } from '@tanstack/react-query'
import './App.css'
function App() {
const { data } = useQuery({
queryKey: ['people'],
queryFn: () =>
fetch('https://swapi.dev/api/people')
.then((res) => res.json())
.then((data) => data.results as { name: string }[]),
initialData: [],
})
return (
<div>
<ul>
{data.map((person) => (
<li key={person.name}>{person.name}</li>
))}
</ul>
</div>
)
}
export default AppYou can find out everything you need to know on how to use React-Query in the React-Query documentation.
Another common requirement for React applications is state management. There are many options for state management in React. TanStack Store provides a great starting point for your project.
First you need to add TanStack Store as a dependency:
npm install @tanstack/storeNow let's create a simple counter in the src/App.tsx file as a demonstration.
import { useStore } from '@tanstack/react-store'
import { Store } from '@tanstack/store'
import './App.css'
const countStore = new Store(0)
function App() {
const count = useStore(countStore)
return (
<div>
<button onClick={() => countStore.setState((n) => n + 1)}>
Increment - {count}
</button>
</div>
)
}
export default AppOne of the many nice features of TanStack Store is the ability to derive state from other state. That derived state will update when the base state updates.
Let's check this out by doubling the count using derived state.
import { useStore } from '@tanstack/react-store'
import { Store, Derived } from '@tanstack/store'
import './App.css'
const countStore = new Store(0)
const doubledStore = new Derived({
fn: () => countStore.state * 2,
deps: [countStore],
})
doubledStore.mount()
function App() {
const count = useStore(countStore)
const doubledCount = useStore(doubledStore)
return (
<div>
<button onClick={() => countStore.setState((n) => n + 1)}>
Increment - {count}
</button>
<div>Doubled - {doubledCount}</div>
</div>
)
}
export default AppWe use the Derived class to create a new store that is derived from another store. The Derived class has a mount method that will start the derived store updating.
Once we've created the derived store we can use it in the App component just like we would any other store using the useStore hook.
You can find out everything you need to know on how to use TanStack Store in the TanStack Store documentation.
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow the existing code style and conventions
- Write tests for new features
- Update documentation for any new functionality
- Ensure all tests pass before submitting PR
This project is licensed under the MIT License - see the LICENSE file for details.
- Frontend Development - Modern React with TypeScript
- UI/UX Design - Responsive design with Tailwind CSS
- Backend Integration - RESTful API integration
- Payment Systems - Secure payment processing
If you encounter any issues or need help:
- Check the Issues page
- Search existing issues before creating a new one
- Provide detailed information about your problem
- Include steps to reproduce the issue
- CarWash-Server - Backend API
- CarWash-Admin - Admin dashboard
- Real-time Notifications - Push notifications for booking updates
- Advanced Analytics - Detailed reporting dashboard
- Multi-language Support - Internationalization
- Loyalty Program - Customer rewards system
- Calendar Integration - Google/Outlook calendar sync
- Review System - Enhanced rating and review features
The booking flow has been restructured into reusable components:
src/components/user/booking-steps/
βββ LocationStep.tsx # Service location selection
βββ ServiceStep.tsx # Service type selection
βββ VehicleStep.tsx # Vehicle information
βββ DetailsStep.tsx # Date/time scheduling
βββ BookingSuccessStep.tsx # Confirmation
Each step component follows a consistent interface pattern:
interface StepProps {
onNext: () => void
onPrevious: () => void
bookingData: BookingFormData
setBookingData: (data: Partial<BookingFormData>) => void
}Built with shadcn/ui components for consistency:
- Forms: Input, Select, Checkbox, DatePicker
- Layout: Card, Dialog, Drawer, Sidebar
- Feedback: Alert, Badge, Progress, Loader
- Navigation: Button, Link, Dropdown Menu
npm run lint # ESLint code analysis
npm run type-check # TypeScript type checking
npm run prettier # Code formattingnpm run test # Run unit tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage report- Multiple vehicle support per user
- Vehicle type-specific service recommendations
- Maintenance history tracking
- GPS-based location detection
- Service area verification
- Real-time distance calculations
- Secure Paystack integration
- Multiple payment methods
- Transaction history
- Refund processing
- Real-time customer support
- Service recommendations
- Booking assistance
- FAQ automation
npm run build # Create production build
npm run preview # Preview production build# Production environment variables
VITE_API_BASE_URL=https://api.carwash.com
VITE_PAYSTACK_PUBLIC_KEY=pk_live_your_live_key
VITE_NODE_ENV=productionBuilt with β€οΈ using React, TypeScript, and TanStack ecosystem.
Ready to revolutionize your car care experience? Get started today! πβ¨