Marketing Hub: RBAC, i18n (AR/EN), tasks overhaul, team/user merge, tutorial

Features:
- Full RBAC with 3 roles (superadmin/manager/contributor)
- Ownership tracking on posts, tasks, campaigns, projects
- Task system: assign to anyone, filter combobox, visibility scoping
- Team members merged into users table (single source of truth)
- Post thumbnails on kanban cards from attachments
- Publication link validation before publishing
- Interactive onboarding tutorial with Settings restart
- Full Arabic/English i18n with RTL layout support
- Language toggle in sidebar, IBM Plex Sans Arabic font
- Brand-based visibility filtering for non-superadmins
- Manager can only create contributors
- Profile completion flow for new users
- Cookie-based sessions (express-session + SQLite)
This commit is contained in:
fahed
2026-02-08 20:46:58 +03:00
commit 35d84b6bff
2240 changed files with 846749 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
export default function StatCard({ icon: Icon, label, value, subtitle, color = 'brand-primary', trend }) {
const colorMap = {
'brand-primary': 'from-indigo-500 to-indigo-600',
'brand-secondary': 'from-pink-500 to-pink-600',
'brand-tertiary': 'from-amber-500 to-amber-600',
'brand-quaternary': 'from-emerald-500 to-emerald-600',
}
const iconBgMap = {
'brand-primary': 'bg-indigo-50 text-indigo-600',
'brand-secondary': 'bg-pink-50 text-pink-600',
'brand-tertiary': 'bg-amber-50 text-amber-600',
'brand-quaternary': 'bg-emerald-50 text-emerald-600',
}
return (
<div className="bg-white rounded-xl border border-border p-5 card-hover">
<div className="flex items-start justify-between">
<div>
<p className="text-sm font-medium text-text-tertiary">{label}</p>
<p className="text-3xl font-bold text-text-primary mt-1">{value}</p>
{subtitle && (
<p className="text-xs text-text-tertiary mt-1">{subtitle}</p>
)}
</div>
<div className={`w-11 h-11 rounded-xl flex items-center justify-center ${iconBgMap[color] || iconBgMap['brand-primary']}`}>
<Icon className="w-5 h-5" />
</div>
</div>
{trend && (
<div className="mt-3 pt-3 border-t border-border-light">
<div className="flex items-center gap-1">
<span className={`text-xs font-medium ${trend > 0 ? 'text-emerald-600' : 'text-red-500'}`}>
{trend > 0 ? '+' : ''}{trend}%
</span>
<span className="text-xs text-text-tertiary">vs last month</span>
</div>
</div>
)}
</div>
)
}