feat: slide panels, task calendar, team management, project editing, collapsible sections

- Add SlidePanel, TaskDetailPanel, PostDetailPanel, TeamPanel, TeamMemberPanel
- Add ProjectEditPanel, CollapsibleSection, DatePresetPicker, TaskCalendarView
- Update App, AuthContext, i18n (ar/en), PostProduction, ProjectDetail, Projects
- Update Settings, Tasks, Team pages
- Update InteractiveTimeline, MemberCard, ProjectCard, TaskCard components
- Update server API utilities
- Remove tracked server/node_modules (now properly gitignored)
This commit is contained in:
fahed
2026-02-19 11:35:42 +03:00
parent e76be78498
commit 4522edeea8
2207 changed files with 3767 additions and 831225 deletions

View File

@@ -10,6 +10,7 @@ import Assets from './pages/Assets'
import Campaigns from './pages/Campaigns'
import CampaignDetail from './pages/CampaignDetail'
import Finance from './pages/Finance'
import Budgets from './pages/Budgets'
import Projects from './pages/Projects'
import ProjectDetail from './pages/ProjectDetail'
import Tasks from './pages/Tasks'
@@ -40,10 +41,11 @@ const TEAM_ROLES = [
export const AppContext = createContext()
function AppContent() {
const { user, loading: authLoading, checkAuth } = useAuth()
const { user, loading: authLoading, checkAuth, hasModule } = useAuth()
const { t, lang } = useLanguage()
const [teamMembers, setTeamMembers] = useState([])
const [brands, setBrands] = useState([])
const [teams, setTeams] = useState([])
const [loading, setLoading] = useState(true)
const [showTutorial, setShowTutorial] = useState(false)
const [showProfilePrompt, setShowProfilePrompt] = useState(false)
@@ -88,11 +90,21 @@ function AppContent() {
}
}
const loadTeams = async () => {
try {
const data = await api.get('/teams')
setTeams(Array.isArray(data) ? data : (data.data || []))
} catch (err) {
console.error('Failed to load teams:', err)
}
}
const loadInitialData = async () => {
try {
const [, brandsData] = await Promise.all([
loadTeam(),
api.get('/brands').then(d => Array.isArray(d) ? d : (d.data || [])).catch(() => []),
loadTeams(),
])
setBrands(brandsData)
} catch (err) {
@@ -123,7 +135,7 @@ function AppContent() {
}
return (
<AppContext.Provider value={{ currentUser: user, teamMembers, brands, loadTeam, getBrandName }}>
<AppContext.Provider value={{ currentUser: user, teamMembers, brands, loadTeam, getBrandName, teams, loadTeams }}>
{/* Profile completion prompt */}
{showProfilePrompt && (
<div className="fixed top-4 right-4 z-50 bg-amber-50 border-2 border-amber-400 rounded-xl shadow-lg p-4 max-w-md animate-fade-in">
@@ -258,18 +270,23 @@ function AppContent() {
<Route path="/login" element={user ? <Navigate to="/" replace /> : <Login />} />
<Route path="/" element={user ? <Layout /> : <Navigate to="/login" replace />}>
<Route index element={<Dashboard />} />
<Route path="posts" element={<PostProduction />} />
<Route path="assets" element={<Assets />} />
<Route path="campaigns" element={<Campaigns />} />
<Route path="campaigns/:id" element={<CampaignDetail />} />
{(user?.role === 'superadmin' || user?.role === 'manager') && (
{hasModule('marketing') && <>
<Route path="posts" element={<PostProduction />} />
<Route path="assets" element={<Assets />} />
<Route path="campaigns" element={<Campaigns />} />
<Route path="campaigns/:id" element={<CampaignDetail />} />
<Route path="brands" element={<Brands />} />
</>}
{hasModule('finance') && (user?.role === 'superadmin' || user?.role === 'manager') && <>
<Route path="finance" element={<Finance />} />
)}
<Route path="projects" element={<Projects />} />
<Route path="projects/:id" element={<ProjectDetail />} />
<Route path="tasks" element={<Tasks />} />
<Route path="budgets" element={<Budgets />} />
</>}
{hasModule('projects') && <>
<Route path="projects" element={<Projects />} />
<Route path="projects/:id" element={<ProjectDetail />} />
<Route path="tasks" element={<Tasks />} />
</>}
<Route path="team" element={<Team />} />
<Route path="brands" element={<Brands />} />
<Route path="settings" element={<Settings />} />
{user?.role === 'superadmin' && (
<Route path="users" element={<Users />} />