Skip to content

rcdevgames/laundry-pickup-microsite

Repository files navigation

Laundry Pickup Microsite

A modern, responsive laundry pickup booking microsite built with React, Vite, and TailwindCSS. Features dark/light theme toggle, professional pricing section, and a clean, accessible booking interface.

Features

  • Welcome Modal: Full-page popup on first visit with click-to-close functionality
  • SweetAlert2 Modals: Beautiful, animated success/error modals for form feedback
  • API Integration: Axios-based HTTP client with interceptors and error handling
  • Service Architecture: Reusable API services to avoid code duplication
  • Lazy Loading: Shimmer effects for pricing section while data loads
  • Responsive Design: Mobile-first approach with TailwindCSS
  • Dark/Light Theme: Toggle between themes with smooth transitions
  • Professional Pricing: Three-tier pricing cards with popular plan highlighting
  • Advanced Form Validation: React Hook Form + Yup with real-time validation
  • Accessibility: WCAG AA compliant with proper ARIA labels and focus management
  • Modern UI: Clean design inspired by AdminLTE with card-based layout

Tech Stack

  • React 18 - UI framework
  • Vite - Build tool and dev server with HMR
  • TailwindCSS 3 - Utility-first CSS framework with custom configuration
  • PostCSS - CSS processing and optimization
  • Autoprefixer - Automatic vendor prefixing
  • React Hook Form - Performant forms with easy validation
  • Yup - JavaScript schema builder for validation
  • SweetAlert2 - Beautiful, responsive, customizable modals
  • Axios - HTTP client for API requests with interceptors
  • Inter Font - Modern, readable typography via Google Fonts
  • SWC - Fast JavaScript/TypeScript compiler

Getting Started

Prerequisites

  • Node.js (version 16 or higher)
  • npm or yarn

Installation

  1. Clone the repository:
git clone <repository-url>
cd laundry-pickup-microsite
  1. Install dependencies:
npm install
  1. Start the development server:
npm run dev
  1. Open your browser and navigate to http://localhost:5173

Available Scripts

  • npm run dev - Start development server
  • npm run build - Build for production
  • npm run preview - Preview production build
  • npm run lint - Run ESLint

Project Structure

laundry-pickup-microsite/
├── index.html              # Root HTML file
├── package.json           # Dependencies and scripts
├── vite.config.js         # Vite configuration
├── src/
│   ├── main.jsx          # Application entry point
│   ├── App.jsx           # Main app component
│   ├── styles.css        # CSS variables for theming
│   ├── services/         # API service layer
│   │   ├── api.js        # Base API configuration and utilities
│   │   ├── pricing.js    # Pricing-related API functions
│   │   └── orders.js     # Order-related API functions
│   └── components/
│       ├── Form.jsx      # Enhanced booking form with API integration
│       ├── Pricing.jsx   # Pricing section with lazy loading
│       ├── Shimmer.jsx   # Loading shimmer component
│       └── WelcomeModal.jsx # Welcome popup component
└── README.md             # This file

Testing Instructions

  1. Welcome Modal (First Visit):
    • Clear localStorage or use incognito mode to see the popup
    • Notice the full-page overlay covering entire screen
    • Click anywhere on the overlay or the close button to dismiss
    • Verify smooth scroll to top after closing
    • Note: Modal only appears once per browser session (uses localStorage)
    • Reset: Run localStorage.removeItem('laundry-visited') in console to test again
  2. Theme Toggle & Dark Mode Compatibility:
    • Click the sun/moon icon in the header to switch between light and dark modes
    • Pricing Section: Verify all buttons have proper contrast in both themes
    • Non-popular Buttons: Should be light gray in light mode, dark gray in dark mode
    • Popular Badge: Should remain blue with white text in both themes
    • Tips Section: Yellow background should adapt to dark theme
    • Form: Check all form elements remain visible in dark mode
    • Modal: Test welcome modal in both themes
  3. Pricing Section:
    • Review the three pricing tiers (Cuci Kering, Cuci + Setrika, VIP Express)
    • Notice the "Paling Populer" badge on the middle tier
    • Click "Pilih Paket Ini" buttons to scroll to the booking form
  4. API Integration & Lazy Loading:
    • Shimmer Loading: Notice the pricing section shows shimmer effect on first load
    • API Caching: Refresh page to see cached data loads instantly
    • Error Handling: Disconnect internet to see fallback to dummy data
  5. Enhanced Form with API:
    • Plan Selection: Choose different pricing plans from dropdown
    • Weight Input: Enter laundry weight (1-50 kg) with validation
    • Real-time Validation: Try typing invalid data to see instant feedback
    • Name Field: Test with numbers/symbols (should show error)
    • WhatsApp Field: Test with invalid formats (e.g., "abc123", "0812345678")
    • Address Field: Test with very short text (< 10 chars)
    • Character Counter: Notice the character counter for address field
    • Submit with Errors: Try submitting with validation errors (warning modal appears)
    • Success Modal: Submit valid data to see detailed success modal with order info
    • Error Modal: Test error scenarios to see error modal with retry option
    • Auto-reset: Form automatically resets after successful submission
  6. Responsiveness: Resize browser window to test mobile layout
  7. Accessibility: Use Tab key to navigate through form elements

Customization

Theme Colors

Modify the CSS variables in src/styles.css to customize the color scheme:

:root {
  --bg-primary: #FFFFFF;
  --fg-primary: #000000;
  --accent: #007ACC;
  /* ... other variables */
}

Form Fields

Edit the form component in src/components/Form.jsx to add or modify fields as needed.

Pricing Plans

Customize the pricing plans in src/components/Pricing.jsx:

const pricingPlans = [
  {
    id: 'basic',
    name: 'Your Plan Name',
    price: 'Rp XX.XXX',
    perUnit: '/kg',
    description: 'Your description',
    features: ['Feature 1', 'Feature 2'],
    popular: false, // Set to true for popular plan
    color: 'border-gray-200 hover:border-gray-300'
  }
];

Welcome Modal

Customize the welcome popup in src/components/WelcomeModal.jsx:

// Change the title and description
<h1 id="welcome-title" className="text-3xl font-bold text-[var(--fg-primary)] mb-2">
  Your Custom Title
</h1>

// Modify the features grid
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
  <div className="p-4 bg-[var(--input-bg)] rounded-lg">
    <div className="text-2xl mb-2">🚚</div>
    <h3 className="font-semibold text-[var(--fg-primary)] mb-1">Your Feature</h3>
    <p className="text-sm text-[var(--fg-primary)] opacity-75">Description</p>
  </div>
</div>

Form Validation Schema

Customize validation rules in src/components/Form.jsx:

// Modify the Yup validation schema
const validationSchema = yup.object({
  name: yup
    .string()
    .required('Custom error message')
    .min(2, 'Minimum characters required')
    .matches(/^[a-zA-Z\s]+$/, 'Only letters and spaces allowed'),
  whatsapp: yup
    .string()
    .required('Phone number is required')
    .matches(/^(\+62|62|0)[8-9][0-9]{7,11}$/, 'Invalid Indonesian phone number'),
  address: yup
    .string()
    .required('Address is required')
    .min(10, 'Address too short')
    .max(200, 'Address too long')
});

SweetAlert2 Modals

Customize modal behavior in src/components/Form.jsx:

// Success modal customization
await Swal.fire({
  icon: 'success',
  title: 'Custom Success Title',
  text: 'Custom success message',
  confirmButtonText: 'Custom Button Text',
  confirmButtonColor: '#007ACC',
  timer: 5000, // Auto close after 5 seconds
  timerProgressBar: true,
  // Add custom animations
  showClass: {
    popup: 'animate__animated animate__fadeInDown'
  },
  hideClass: {
    popup: 'animate__animated animate__fadeOutUp'
  }
});

// Error modal customization
await Swal.fire({
  icon: 'error',
  title: 'Custom Error Title',
  text: 'Custom error message',
  confirmButtonText: 'Try Again',
  confirmButtonColor: '#007ACC'
});

Tailwind CSS Customization

The project uses a fully configured Tailwind CSS setup with custom utilities and components:

Custom Colors

/* In tailwind.config.js */
colors: {
  'laundry': {
    primary: '#007ACC',    // Main brand color
    secondary: '#6B7280',  // Secondary text
    success: '#10B981',    // Success states
    warning: '#F59E0B',    // Warning states
    danger: '#EF4444',     // Error states
    info: '#3B82F6',       // Info states
  }
}

Custom Components

/* In src/styles.css */
@layer components {
  .btn-primary {
    @apply bg-[var(--accent)] text-white px-4 py-2 rounded-md font-medium
           hover:bg-blue-600 focus:ring-2 focus:ring-[var(--accent)] focus:ring-offset-2
           transition-colors duration-200;
  }

  .card {
    @apply bg-[var(--card-bg)] border border-[var(--border)] rounded-lg shadow-md p-6;
  }

  .input-field {
    @apply w-full p-3 border border-[var(--border)] rounded-md bg-[var(--input-bg)]
           text-[var(--fg-primary)] focus:ring-2 focus:ring-[var(--accent)] focus:outline-none
           transition-colors duration-200;
  }
}

Custom Animations

/* Custom keyframes in tailwind.config.js */
animation: {
  'fade-in': 'fadeIn 0.5s ease-in-out',
  'slide-up': 'slideUp 0.3s ease-out',
  'bounce-slow': 'bounce 2s infinite',
  'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
  'shimmer': 'shimmer 1.5s infinite',
}

Usage Examples

// Use custom colors
<div className="bg-laundry-primary text-white">Primary Button</div>

// Use custom components
<input className="input-field" placeholder="Enter text" />

// Use custom animations
<div className="animate-fade-in">Fade in content</div>

// Use utility classes
<div className="glass-effect backdrop-blur-sm">Glass morphism effect</div>

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

License

MIT License - feel free to use this project for your own purposes.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published