A modern, full-stack web application for managing industrial zone rentals with real-time notifications and multi-image support.
- Features
- System Architecture
- Tech Stack
- Project Structure
- Quick Start
- API Documentation
- Key Features Deep Dive
- Development Standards
- Team
- Industrial Zone Management: Browse, search, and filter available industrial zones
- Rental Request System: Submit rental requests with customizable area and duration
- Smart Approval Workflow: Admin approval/rejection with automated contract generation
- Contract Management: View active and historical rental contracts
- Real-time Notifications: Instant alerts for request approvals, rejections, and updates
- Multi-Image Upload: Support 1-6 images per zone with preview and management
- Role-Based Access Control: Separate ADMIN and TENANT interfaces with permission enforcement
- Real-time Notifications: Polling-based notification system with badge display
- JWT Authentication: Secure token-based authentication with refresh token support
- Responsive UI: Neumorphism design system with smooth transitions and hover effects
- RESTful API: Clean, well-documented API endpoints for all business operations
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INDUSTRIAL ZONE RENTAL PLATFORM β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ββββββββββββββββββββββββ ββββββββββββββββββββββββ β
β β FRONTEND (React) β β BACKEND (Django) β β
β β Port: 3000 ββββββHTTPβββββΊβ Port: 8000 β β
β β β REST API β β β
β ββββββββββββββββββββββββ€ ββββββββββββββββββββββββ€ β
β β Components: β β API Endpoints: β β
β β β’ Navbar β β β’ /api/zones/ β β
β β β’ Zone List/Detail β β β’ /api/rentals/ β β
β β β’ Rental Requests β β β’ /api/contracts/ β β
β β β’ Contracts β β β’ /api/notifications/β β
β β β’ Dashboard β β β’ /api/auth/ β β
β β β’ Admin Panel β β β β
β β β β Models: β β
β β State Management: β β β’ User/Profile β β
β β β’ AuthContext β β β’ IndustrialZone β β
β β β’ Local State β β β’ ZoneImage β β
β β β’ Polling β β β’ RentalRequest β β
β β β β β’ Contract β β
β β Styling: β β β’ Notification β β
β β β’ Inline CSS β β β β
β β β’ CSS Variables β β Database: β β
β β β’ Neumorphism β β β’ SQLite (dev) β β
β β β β β’ PostgreSQL (prod) β β
β ββββββββββββββββββββββββ ββββββββββββββββββββββββ β
β β β β
β ββββββββββββββββββββ¬ββββββββββββββββββββ β
β β β
β ββββββββββΌβββββββββ β
β β File Storage β β
β β Media/images/ β β
β βββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Data Flow:
1. User submits rental request β Request stored in DB
2. Admin approves request β Contract created + Notification sent
3. User polls notifications endpoint β Badge updates
4. User views zones β First image displayed from ZoneImage model
| Layer | Technology | Version |
|---|---|---|
| Framework | Django | 5.0.1 |
| API | Django REST Framework | 3.14.0 |
| Authentication | djangorestframework-simplejwt | 5.3.1 |
| CORS | django-cors-headers | 4.3.1 |
| Database | SQLite (dev) / PostgreSQL (prod) | Latest |
| Language | Python | 3.9+ |
| Layer | Technology | Version |
|---|---|---|
| Framework | React | 19.2.4 |
| Routing | React Router DOM | 7.14.0 |
| HTTP Client | Axios | 1.14.0 |
| Language | JavaScript (ES6+) | - |
| Build Tool | React Scripts | 5.0.1 |
- Neumorphism: Soft UI with elevation and depth
- CSS Variables: Dynamic theming support
- Inline Styles: Component-scoped styling for consistency
- Responsive Design: Mobile-first approach with CSS custom properties
BTL_python/
βββ backend/ # Django REST API
β βββ api/
β β βββ models.py # Database models (User, Zone, RentalRequest, etc.)
β β βββ views.py # API viewsets & endpoints
β β βββ serializers.py # Data serialization (request/response)
β β βββ urls.py # API route definitions
β β βββ admin.py # Django admin configuration
β β βββ permissions.py # Custom permission classes
β β βββ migrations/ # Database migration files
β βββ config/
β β βββ settings.py # Django settings (DB, CORS, AUTH)
β β βββ urls.py # Main URL router
β β βββ wsgi.py # WSGI application
β β βββ asgi.py # ASGI application
β βββ requirements.txt # Python dependencies
β βββ manage.py # Django CLI
β βββ media/ # Uploaded zone images (FileField storage)
β
βββ frontend/ # React application
β βββ public/
β β βββ index.html # HTML template
β βββ src/
β β βββ pages/
β β β βββ LoginPage.js # User login & registration
β β β βββ DashboardPage.js # Main dashboard (contracts/requests)
β β β βββ ZoneListPage.js # Browse zones
β β β βββ ZoneDetailPage.js # Single zone details + images
β β β βββ RentalRequestListPage.js # View rental requests
β β β βββ RentalRequestDetailPage.js # Request details & actions
β β β βββ ContractListPage.js # View contracts
β β β βββ ZoneFormPage.js # Admin: create/edit zones
β β β βββ ProfilePage.js # User profile settings
β β βββ components/
β β β βββ Navbar.js # Navigation with notification badge
β β β βββ ZoneCard.js # Zone card with first image
β β β βββ ImageGallery.js # Multi-image display
β β β βββ StatusBadge.js # Status indicators
β β β βββ TablePagination.js # Table pagination controls
β β β βββ ZoneImagePlaceholder.js # Fallback image gradient
β β β βββ (other components)
β β βββ contexts/
β β β βββ AuthContext.js # Authentication state & logic
β β βββ services/
β β β βββ api.js # Axios instance with interceptors
β β β βββ authService.js # Login/register/logout
β β β βββ zoneService.js # Zone CRUD & search
β β β βββ rentalService.js # Rental request operations
β β β βββ contractService.js # Contract queries
β β β βββ notificationService.js # Notification polling
β β β βββ imageService.js # Image upload & management
β β βββ App.js # Main component & routing
β β βββ index.css # Global styles & CSS variables
β β βββ index.js # React DOM render
β βββ package.json # NPM dependencies
β βββ .env.example # Environment template
β
βββ docs/ # Project documentation
β βββ project-overview-pdr.md
β βββ system-architecture.md
β βββ code-standards.md
β βββ design-guidelines.md
β βββ deployment-guide.md
β
βββ README.md # This file
- Python 3.9+ with pip
- Node.js 16+ with npm
- PostgreSQL or SQLite (SQLite for development)
- Git for version control
# Clone the repository
git clone <repository-url>
cd BTL_python/backend
# Create Python virtual environment
python -m venv .venv
# Activate virtual environment
# On Windows:
.venv\Scripts\activate
# On macOS/Linux:
source .venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Create .env file (optional)
# Copy environment variables as needed
# Run migrations
python manage.py migrate
# Create superuser (admin account)
python manage.py createsuperuser
# Start development server
python manage.py runserver
# Server runs on http://127.0.0.1:8000# Navigate to frontend
cd ../frontend
# Install dependencies
npm install
# Create .env file (optional, if needed)
# REACT_APP_API_URL=http://127.0.0.1:8000
# Start development server
npm start
# App opens at http://localhost:3000- Register Account: Create TENANT or ADMIN account on login page
- Browse Zones: View available industrial zones with images
- Submit Request: Tenants can submit rental requests
- Admin Actions: Admins can approve/reject requests (auto-creates contracts)
- Track Notifications: Real-time badge shows updates
POST /api/auth/register/ # User registration
POST /api/auth/login/ # User login (returns JWT tokens)
POST /api/auth/logout/ # User logout
GET /api/auth/me/ # Current user info
PATCH /api/auth/profile/ # Update user profile
GET /api/zones/ # List zones (search, filter, paginate)
GET /api/zones/{id}/ # Zone details + images
POST /api/zones/ # Create zone (admin only)
PATCH /api/zones/{id}/ # Update zone (admin only)
DELETE /api/zones/{id}/ # Delete zone (admin only)
GET /api/zones/{zone_id}/images/ # List zone images
POST /api/zones/{zone_id}/images/ # Upload image (admin only)
DELETE /api/zones/{zone_id}/images/{id}/ # Delete image (admin only)
GET /api/rentals/ # List requests (filtered by user role)
POST /api/rentals/ # Create rental request (tenant)
GET /api/rentals/{id}/ # Request details
POST /api/rentals/{id}/approve/ # Approve (admin only)
POST /api/rentals/{id}/reject/ # Reject (admin only)
POST /api/rentals/{id}/cancel/ # Cancel (tenant, if pending)
GET /api/contracts/ # List contracts (filtered by user role)
GET /api/contracts/{id}/ # Contract details
GET /api/contracts/my_active/ # Current user's active contracts
GET /api/contracts/active/ # All active contracts (admin only)
GET /api/notifications/ # List notifications
GET /api/notifications/unread-count/ # Unread count
POST /api/notifications/mark-as-read/ # Mark as read
POST /api/notifications/{id}/mark_single/ # Mark single notification
Backend (models.py)
ZoneImagemodel: ForeignKey toIndustrialZone- ImageField for file storage in
/media/images/ - Min 1, max 6 images per zone enforced at serializer level
Frontend (ZoneFormPage.js)
- Drag-and-drop image upload
- Local preview before submission
- Separate management for existing vs new images
- Individual delete buttons with confirmation
- Real-time validation for image count limits
Data Flow
User selects images β FileReader previews β FormData multipart upload
β Django receives β ImageField saves to media β URL returned
β Frontend stores in ZoneImage β Displayed on zone cards/detail
Backend (models.py & views.py)
Notificationmodel: recipient, actor, verb, target_id, is_read, created_at- NotificationViewSet with custom actions:
/unread-count/- Returns unread notification count/mark-as-read/- Bulk or individual mark as read
Frontend (Navbar.js & notificationService.js)
- 30-second polling interval to
/api/notifications/unread-count/ - Badge displays unread count (shows "99+" if >99)
- Auto-clears badge after 5 seconds on page visit
- Smooth pop animation when new notifications appear
Notification Triggers
Tenant creates rental request β Notification created for Admin
Admin approves request β Notification created for Tenant + Contract created
Admin rejects request β Notification created for Tenant
User Roles
- ADMIN: Full system access (zones, requests, users, contracts)
- TENANT: Limited access (own requests, view zones, own contracts)
Permission Enforcement
- Frontend conditionally renders UI based on
isAdmin() - Backend decorators enforce permissions at endpoint level
- API returns 403 FORBIDDEN for unauthorized actions
- Profile page shows role badge (π for admin, π€ for tenant)
CSS Variables (globals.css)
--color-background: #f0f2f5;
--color-foreground: #1a1a1a;
--color-accent: #6c63ff;
--shadow-extruded: 10px 10px 20px #d0d5dd, -10px -10px 20px #ffffff;Component Styling
- All components use inline styles for scoping
- Hover states with smooth transitions
- Consistent border radius via
--radius-baseand--radius-inner - Box shadows for depth and elevation
Benefits
- Soft, modern aesthetic
- Improved visual hierarchy
- Reduced cognitive load (UI feels tactile)
- Excellent for industrial/professional themes
Request Lifecycle
PENDING β APPROVED (contract created) or REJECTED
β
APPROVED β Active contract until end date
REJECTED β Tenant notified, can resubmit
Admin Actions
-
View pending requests in dashboard
-
Click "Approve" with optional admin note
-
System auto-creates contract with:
- Start date: today
- End date: today + rental_duration months
- Monthly rent from request calculation
- Status: ACTIVE
-
Tenant receives notification immediately
-
Contract appears in tenant's contract list
- No TypeScript: Pure JavaScript (ES6+) for simplicity
- Functional Components: React hooks (useState, useEffect, useCallback)
- No MUI/Tailwind: Inline styles + CSS variables for complete control
- Service Layer: Axios services abstract API calls
- Context API: AuthContext for global state management
- Components: PascalCase (
ZoneCard.js,Navbar.js) - Pages: PascalCase ending in "Page" (
ZoneListPage.js) - Services: camelCase (
zoneService.js,notificationService.js) - Utilities: camelCase (
formatPrice.js,validateEmail.js)
- Indentation: 2 spaces
- Semicolons: Always use
- Comments: For complex logic only
- Props: Validate at component level
- State: Lift state only when necessary
// services/zoneService.js
import api from './api';
export const zoneService = {
getAllZones: async (params) => {
const { data } = await api.get('/api/zones/', { params });
return data;
},
getZoneById: async (id) => {
const { data } = await api.get(`/api/zones/${id}/`);
return data;
}
};// Use local state for component-level data
const [zones, setZones] = useState([]);
const [loading, setLoading] = useState(true);
// Use AuthContext for global auth state
const { user, isAdmin } = useAuth();
// Use effect for data fetching
useEffect(() => {
loadData();
}, [dependencies]);Project Lead: Anh TrαΊ§n
Role: Full-stack Developer
Responsibilities:
- Architecture design and system implementation
- Backend API development (Django REST Framework)
- Frontend implementation (React with Neumorphism design)
- Database design and optimization
- Documentation and code standards
Contact: trananh22052005@gmail.com
This project is proprietary software. All rights reserved.
Usage Restrictions:
- Unauthorized copying, modification, or distribution is prohibited
- Contact project owner for licensing inquiries
For issues, questions, or feature requests:
- Check existing documentation in
/docsfolder - Review API endpoints in this README
- Check backend logs:
python manage.py runserver(verbose mode) - Check frontend console: Open browser DevTools (F12)
- Backend: http://127.0.0.1:8000 (development)
- Frontend: http://localhost:3000 (development)
- API Root: http://127.0.0.1:8000/api/
- Django Admin: http://127.0.0.1:8000/admin/
- API Documentation: See API Documentation section
Last Updated: April 2026
Status: Complete & Production Ready