feat: Complete Z.CRM system with all 6 modules

 Features:
- Complete authentication system with JWT
- Dashboard with all 6 modules visible
- Contact Management module (Salesforce-style)
- CRM & Sales Pipeline module (Pipedrive-style)
- Inventory & Assets module (SAP-style)
- Tasks & Projects module (Jira/Asana-style)
- HR Management module (BambooHR-style)
- Marketing Management module (HubSpot-style)
- Admin Panel with user management and role matrix
- World-class UI/UX with RTL Arabic support
- Cairo font (headings) + Readex Pro font (body)
- Sample data for all modules
- Protected routes and authentication flow
- Backend API with Prisma + PostgreSQL
- Comprehensive documentation

🎨 Design:
- Color-coded modules
- Professional data tables
- Stats cards with metrics
- Progress bars and status badges
- Search and filters
- Responsive layout

📊 Tech Stack:
- Frontend: Next.js 14, TypeScript, Tailwind CSS
- Backend: Node.js, Express, Prisma
- Database: PostgreSQL
- Auth: JWT with bcrypt

🚀 Production-ready frontend with all features accessible
This commit is contained in:
Talal Sharabi
2026-01-06 18:43:43 +04:00
commit 35daa52767
82 changed files with 29445 additions and 0 deletions

View File

@@ -0,0 +1,154 @@
'use client'
import React, { createContext, useContext, useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'
interface User {
id: string
employeeId: string
username: string
email: string
isActive: boolean
role?: {
id: string
name: string
nameEn: string
permissions: Permission[]
}
}
interface Permission {
id: string
module: string
canView: boolean
canCreate: boolean
canEdit: boolean
canDelete: boolean
canExport: boolean
canApprove: boolean
}
interface AuthContextType {
user: User | null
login: (email: string, password: string) => Promise<void>
logout: () => void
isLoading: boolean
isAuthenticated: boolean
hasPermission: (module: string, action: 'view' | 'create' | 'edit' | 'delete' | 'export' | 'approve') => boolean
}
const AuthContext = createContext<AuthContextType | undefined>(undefined)
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [user, setUser] = useState<User | null>(null)
const [isLoading, setIsLoading] = useState(true)
const router = useRouter()
// Check for existing token on mount
useEffect(() => {
const token = localStorage.getItem('token')
if (token) {
// Verify token and get user data
fetchUserData(token)
} else {
setIsLoading(false)
}
}, [])
const fetchUserData = async (token: string) => {
try {
const response = await fetch('http://localhost:5001/api/v1/auth/me', {
headers: {
'Authorization': `Bearer ${token}`
}
})
if (response.ok) {
const userData = await response.json()
setUser(userData.data)
} else {
localStorage.removeItem('token')
}
} catch (error) {
console.error('Failed to fetch user data:', error)
localStorage.removeItem('token')
} finally {
setIsLoading(false)
}
}
const login = async (email: string, password: string) => {
try {
const response = await fetch('http://localhost:5001/api/v1/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ email, password })
})
const data = await response.json()
if (!response.ok) {
throw new Error(data.message || 'فشل تسجيل الدخول')
}
// Store token
localStorage.setItem('token', data.data.accessToken)
// Set user data
setUser(data.data.user)
// Redirect to dashboard
router.push('/dashboard')
} catch (error: any) {
throw new Error(error.message || 'فشل تسجيل الدخول')
}
}
const logout = () => {
localStorage.removeItem('token')
setUser(null)
router.push('/')
}
const hasPermission = (module: string, action: 'view' | 'create' | 'edit' | 'delete' | 'export' | 'approve'): boolean => {
if (!user?.role?.permissions) return false
const permission = user.role.permissions.find(p => p.module.toLowerCase() === module.toLowerCase())
if (!permission) return false
const actionMap = {
view: 'canView',
create: 'canCreate',
edit: 'canEdit',
delete: 'canDelete',
export: 'canExport',
approve: 'canApprove'
}
return permission[actionMap[action] as keyof Permission] as boolean
}
return (
<AuthContext.Provider value={{
user,
login,
logout,
isLoading,
isAuthenticated: !!user,
hasPermission
}}>
{children}
</AuthContext.Provider>
)
}
export function useAuth() {
const context = useContext(AuthContext)
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider')
}
return context
}