|
1 | | -# React + Vite |
| 1 | +# 🖊️ Tulis - Stationery E-commerce Platform |
2 | 2 |
|
3 | | -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. |
| 3 | +A modern, responsive e-commerce platform for stationery products built with React, Firebase, and Tailwind CSS. Features a comprehensive dark theme system, user authentication, and admin management capabilities. |
4 | 4 |
|
5 | | -Currently, two official plugins are available: |
| 5 | + |
6 | 6 |
|
7 | | -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh |
8 | | -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh |
| 7 | +## ✨ Features |
9 | 8 |
|
10 | | -## Expanding the ESLint configuration |
| 9 | +### 🛍️ **E-commerce Functionality** |
11 | 10 |
|
12 | | -If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. |
| 11 | +- **Product Catalog**: Browse stationery items with categories (Pen, Pencil, Brush, Case) |
| 12 | +- **Product Filtering & Sorting**: Filter by category and sort by price (low to high, high to low) |
| 13 | +- **Shopping Cart**: Add items to cart with quantity management |
| 14 | +- **Product Details**: Detailed product pages with images and descriptions |
| 15 | +- **Responsive Design**: Mobile-first design that works on all devices |
| 16 | + |
| 17 | +### 👤 **User Authentication** |
| 18 | + |
| 19 | +- **Email/Password Login**: Traditional authentication with Firebase Auth |
| 20 | +- **Google OAuth**: One-click sign-in with Google |
| 21 | +- **User Registration**: Secure account creation with validation |
| 22 | +- **Role-based Access**: Separate interfaces for customers and admins |
| 23 | +- **Session Management**: Persistent login state with automatic redirects |
| 24 | + |
| 25 | +### 🎨 **Advanced UI/UX** |
| 26 | + |
| 27 | +- **Dark/Light Theme**: Toggle between themes with system preference detection |
| 28 | +- **Theme Persistence**: Remembers user's theme preference across sessions |
| 29 | +- **Smooth Animations**: CSS transitions and hover effects throughout |
| 30 | +- **Loading States**: Skeleton loaders and loading indicators |
| 31 | +- **Error Handling**: User-friendly error messages and alerts |
| 32 | + |
| 33 | +### 🔧 **Admin Panel** |
| 34 | + |
| 35 | +- **Product Management**: Add, edit, and delete products |
| 36 | +- **Inventory Control**: Manage stock levels and product information |
| 37 | +- **Image Upload**: Cloudinary integration for product images |
| 38 | +- **Data Tables**: Sortable product tables with bulk actions |
| 39 | +- **Real-time Updates**: Instant UI updates after data changes |
| 40 | + |
| 41 | +### 🛠️ **Technical Features** |
| 42 | + |
| 43 | +- **State Management**: Redux Toolkit for global state |
| 44 | +- **Real-time Database**: Firebase Firestore for data persistence |
| 45 | +- **Image Hosting**: Cloudinary for optimized image storage |
| 46 | +- **Routing**: React Router with protected routes |
| 47 | +- **Form Validation**: Client-side and server-side validation |
| 48 | +- **Error Boundaries**: Graceful error handling throughout the app |
| 49 | + |
| 50 | +## 🚀 Getting Started |
| 51 | + |
| 52 | +### Prerequisites |
| 53 | + |
| 54 | +- Node.js (v16 or higher) |
| 55 | +- npm or yarn |
| 56 | +- Firebase account |
| 57 | +- Cloudinary account (for image uploads) |
| 58 | + |
| 59 | +### Installation |
| 60 | + |
| 61 | +1. **Clone the repository** |
| 62 | + |
| 63 | + ```bash |
| 64 | + git clone https://github.com/yourusername/tulis.git |
| 65 | + cd tulis |
| 66 | + ``` |
| 67 | + |
| 68 | +2. **Install dependencies** |
| 69 | + |
| 70 | + ```bash |
| 71 | + npm install |
| 72 | + ``` |
| 73 | + |
| 74 | +3. **Environment Setup** |
| 75 | + Create a `.env` file in the root directory: |
| 76 | + |
| 77 | + ```env |
| 78 | + # Firebase (matches src/config/firebase.js) |
| 79 | + VITE_API_KEY=your_firebase_api_key |
| 80 | + VITE_AUTH_DOMAIN=your_firebase_auth_domain |
| 81 | + VITE_PROJECT_ID=your_firebase_project_id |
| 82 | + VITE_STORAGE_BUCKET=your_firebase_storage_bucket |
| 83 | + VITE_MESSAGING_SENDER_ID=your_firebase_messaging_sender_id |
| 84 | + VITE_APP_ID=your_firebase_app_id |
| 85 | + VITE_MEASUREMENT_ID=your_firebase_measurement_id |
| 86 | +
|
| 87 | + # Optional: if you parameterize Cloudinary later |
| 88 | + # VITE_CLOUDINARY_CLOUD_NAME=your_cloudinary_cloud_name |
| 89 | + # VITE_CLOUDINARY_UPLOAD_PRESET=your_cloudinary_upload_preset |
| 90 | + ``` |
| 91 | + |
| 92 | +4. **Firebase Configuration** |
| 93 | + |
| 94 | + - Create a Firebase project |
| 95 | + - Enable Authentication (Email/Password and Google) |
| 96 | + - Create a Firestore database (native mode) |
| 97 | + - Add your Firebase config to `src/config/firebase.js` (already wired to use the `.env` variables above) |
| 98 | + |
| 99 | +5. **Cloudinary Setup** |
| 100 | + |
| 101 | + - Add the Cloudinary upload widget script (already included in `index.html`): |
| 102 | + ```html |
| 103 | + <script |
| 104 | + src="https://upload-widget.cloudinary.com/global/all.js" |
| 105 | + type="text/javascript" |
| 106 | + ></script> |
| 107 | + ``` |
| 108 | + - Configure `cloudName` and `uploadPreset` in `src/components/UploadWidget.jsx` |
| 109 | + (currently hardcoded to `dvkwdyyc7` and `tulis-image`). Replace with your values. |
| 110 | + |
| 111 | +6. **Run the development server** |
| 112 | + |
| 113 | + ```bash |
| 114 | + npm run dev |
| 115 | + ``` |
| 116 | + |
| 117 | +7. **Build for production** |
| 118 | + ```bash |
| 119 | + npm run build |
| 120 | + ``` |
| 121 | + |
| 122 | +### Scripts |
| 123 | + |
| 124 | +- `npm run dev` — start Vite dev server |
| 125 | +- `npm run build` — build for production |
| 126 | +- `npm run preview` — preview the production build |
| 127 | +- `npm run lint` — run ESLint |
| 128 | + |
| 129 | +## 📁 Project Structure |
| 130 | + |
| 131 | +``` |
| 132 | +tulis/ |
| 133 | +├── src/ |
| 134 | +│ ├── app/ # Redux store and actions |
| 135 | +│ ├── components/ # Reusable UI components |
| 136 | +│ ├── config/ # Firebase and external service configs |
| 137 | +│ ├── context/ # React context (ThemeContext, ThemeProvider, AuthContext, AuthProvider) |
| 138 | +│ ├── hooks/ # Custom hooks/utilities (login/register/google login) |
| 139 | +│ ├── layouts/ # Layout components |
| 140 | +│ ├── pages/ # Page components |
| 141 | +│ ├── router/ # Routing configuration |
| 142 | +│ ├── utils/ # Utility functions (SweetAlert wrappers) |
| 143 | +│ └── assets/ # Static assets |
| 144 | +├── public/ # Public assets |
| 145 | +├── firebase.json # Firebase hosting config (SPA rewrites to index.html) |
| 146 | +└── package.json # Dependencies and scripts |
| 147 | +``` |
| 148 | + |
| 149 | +## 🗃️ Data Model (Firestore) |
| 150 | + |
| 151 | +- `users/{uid}`: `{ name: string, email: string, role: 'customer' | 'admin' }` |
| 152 | +- `products/{id}`: `{ name, desc, images, category, price: number, stock: number }` |
| 153 | +- `cart/{id}`: `{ userId, productId, qty: number, status: 'unpaid', totalPrice: number }` |
| 154 | + |
| 155 | +> Note: Admin access is controlled via the `role` field in `users`. Set `role: 'admin'` to grant admin panel access. |
| 156 | +
|
| 157 | +## 🔐 Routing & Access Control |
| 158 | + |
| 159 | +- Public routes: `/`, `/login`, `/register`, `/cart`, `/detail-product/:id` |
| 160 | +- Protected admin routes: `/admin`, `/add-product`, `/edit-product/:id` |
| 161 | +- `ProtectedRoute` checks `AuthContext` for `user` and `role`. |
| 162 | + |
| 163 | +## 🛠️ Technologies Used |
| 164 | + |
| 165 | +- **Frontend**: React 19, Vite |
| 166 | +- **Styling**: Tailwind CSS 4 |
| 167 | +- **State Management**: Redux Toolkit (slices: `product`, `cart`) |
| 168 | +- **Routing**: React Router DOM |
| 169 | +- **Authentication**: Firebase Auth |
| 170 | +- **Database**: Firebase Firestore |
| 171 | +- **Image Hosting**: Cloudinary (Upload Widget) |
| 172 | +- **UI Components**: Lucide React Icons |
| 173 | +- **Notifications**: SweetAlert2 |
| 174 | +- **Deployment**: Firebase Hosting |
| 175 | + |
| 176 | +## 🎨 Theme System |
| 177 | + |
| 178 | +The application features a comprehensive dark/light theme system: |
| 179 | + |
| 180 | +- **Automatic Detection**: Detects system theme preference |
| 181 | +- **Manual Toggle**: User can switch themes manually |
| 182 | +- **Persistence**: Remembers theme choice across sessions (localStorage) |
| 183 | +- **CSS Variables**: Consistent theming across all components |
| 184 | +- **Smooth Transitions**: 0.3s ease transitions for theme changes |
| 185 | + |
| 186 | +## 🚀 Deployment |
| 187 | + |
| 188 | +### Firebase Hosting |
| 189 | + |
| 190 | +```bash |
| 191 | +npm run build |
| 192 | +firebase deploy |
| 193 | +``` |
| 194 | + |
| 195 | +`firebase.json` is preconfigured with SPA rewrites to `index.html`. |
| 196 | + |
| 197 | +### Environment Variables |
| 198 | + |
| 199 | +Ensure all environment variables are set in your hosting platform: |
| 200 | + |
| 201 | +- Firebase configuration (see `.env` section) |
| 202 | +- Cloudinary credentials (if you parameterize them) |
| 203 | + |
| 204 | +## 📄 License |
| 205 | + |
| 206 | +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. |
| 207 | + |
| 208 | +## 🙏 Acknowledgments |
| 209 | + |
| 210 | +- Firebase for backend services |
| 211 | +- Cloudinary for image hosting |
| 212 | +- Tailwind CSS for styling |
| 213 | +- React community for excellent documentation |
| 214 | +- Lucide for beautiful icons |
| 215 | + |
| 216 | +--- |
| 217 | + |
| 218 | +**Built with ❤️ using React, Firebase, and Tailwind CSS** |
0 commit comments