Files
marketing-app/IMPLEMENTATION_SUMMARY.md
fahed 35d84b6bff 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)
2026-02-08 20:46:58 +03:00

12 KiB

Samaya Marketing Dashboard - Implementation Summary

Date: February 8, 2026
Changes: User Management, Visibility Control, and Interactive Tutorial

Overview

Successfully implemented four major feature enhancements to the Samaya Marketing Dashboard:

  1. User Creation Flow (Manager access + Profile completion)
  2. Brand-based Visibility Filtering
  3. Manager Role Restrictions (Contributors only)
  4. Interactive Tutorial System

1. User Creation Flow

Server Changes

File: server/server.js

  • Modified POST /api/users/team:

    • Now allows both superadmins AND managers to create users
    • Managers can only create users with role='contributor' (403 error if they try other roles)
    • Requires email and name fields
    • Supports optional password (defaults to 'changeme123')
  • Added GET /api/users/me/profile:

    • Returns current user's profile (name, email, team_role, brands, phone)
    • Accessible to all authenticated users
  • Added PATCH /api/users/me/profile:

    • Allows users to edit their own name, team_role, brands, phone
    • Updates session name if changed
    • Accessible to all authenticated users
  • Modified GET /api/auth/me:

    • Now returns tutorial_completed field
    • Calculates and returns profileComplete (true if team_role AND brands are set)
    • Returns brands as parsed JSON array

Client Changes

File: client/src/pages/Team.jsx

  • Added "My Profile" button visible to all users

  • Added "New Member" button for managers (creates contributors only)

  • Form adapts based on:

    • Editing self: shows name, team_role, brands, phone (no email/password)
    • Manager creating: shows name, email, password, team_role, brands, phone (role fixed to contributor)
    • Superadmin creating: full access to all fields including role selector
  • Profile completion prompt in App.jsx:

    • Shows amber banner at top-right if profile incomplete
    • Links to Team page to complete profile
    • Dismissable (shows "Later" button)

2. Brand-based Visibility Filtering

Server Changes

File: server/server.js

  • Modified GET /api/users/team:
    if (req.session.userRole !== 'superadmin') {
      const currentUser = db.prepare('SELECT brands FROM users WHERE id = ?').get(req.session.userId);
      const myBrands = JSON.parse(currentUser?.brands || '[]');
    
      filteredUsers = users.filter(u => {
        const theirBrands = JSON.parse(u.brands || '[]');
        return u.id === req.session.userId || theirBrands.some(b => myBrands.includes(b));
      });
    }
    

Behavior

  • Superadmin: Sees all team members (9 total)
  • Manager/Contributor: Only sees team members who share at least one brand
  • Always includes self in the list
  • Applied to:
    • Team page display
    • Task assignment dropdowns (via teamMembers context)
    • Any component consuming team members

Test Results

Manager with brands ["Samaya Investment", "Hira Cultural District"] sees:

  • Fahed Mahidi (shares both brands)
  • Anas Mater (shares both brands)
  • Sara Al-Zahrani (shares Samaya Investment)
  • Noura (shares both brands)
  • Saeed Ghanem (only has religious exhibition brands)
  • Muhammad Nu'man (only has Google Maps)

3. Manager Role Restrictions

Server Validation

File: server/server.js

let userRole = role || 'contributor';
if (req.session.userRole === 'manager') {
  if (userRole !== 'contributor') {
    return res.status(403).json({ error: 'Managers can only create users with contributor role' });
  }
  userRole = 'contributor';
}

Client UI

File: client/src/pages/Team.jsx

  • Managers see simplified form:
    • No role selector (fixed to "Contributor" with disabled input)
    • Helper text: "Fixed role for managers"
  • Button text changes from "Add Member" to "New Member" for managers

Test Results

  • Manager creates contributor with email "contributor@test.com" → Success
  • Manager tries to create manager with role="manager" → 403 error: "Managers can only create users with contributor role"

4. Interactive Tutorial System

Database Changes

File: server/db.js

  • Added tutorial_completed INTEGER DEFAULT 0 column to users table
  • Migration runs automatically on server start

Server Endpoints

File: server/server.js

  1. PATCH /api/users/me/tutorial:

    • Body: { completed: true/false }
    • Sets tutorial_completed to 0 or 1
    • Returns: { success: true, tutorial_completed: 0|1 }
  2. Modified GET /api/auth/me:

    • Now includes tutorial_completed field in response

Tutorial Component

File: client/src/components/Tutorial.jsx

Features:

  • 8-step interactive walkthrough
  • Dark overlay with spotlight effect on target elements
  • Smooth animations and transitions
  • Progress bar showing step N of 8
  • Navigation: Next, Back, Skip buttons
  • Auto-positions tooltip based on target location
  • Matches app's dark theme aesthetic

Tutorial Steps:

  1. Dashboard → "Your command center..."
  2. Campaigns → "Plan and manage marketing campaigns..."
  3. Post Production → "Create, review, and publish content..."
  4. Tasks → "Assign and track tasks..."
  5. Team → "Your team directory..."
  6. Assets → "Upload and manage creative assets..."
  7. New Post button → "Start creating content here..."
  8. Filter controls → "Use filters to focus..."

Settings Page

File: client/src/pages/Settings.jsx

  • Simple page with "Restart Tutorial" button
  • Sets tutorial_completed to 0 and reloads page
  • Shows success message before reload
  • Placeholder for future settings (notifications, display preferences)

Integration

File: client/src/App.jsx

  • Checks user.tutorial_completed === 0 on load
  • Mounts <Tutorial> component if true
  • Calls handleTutorialComplete() which sets tutorial_completed to 1
  • Profile completion prompt also integrated here

File: client/src/components/Sidebar.jsx

  • Added data-tutorial attributes to nav links:
    • data-tutorial="dashboard" → Dashboard link
    • data-tutorial="campaigns" → Campaigns link
    • data-tutorial="posts" → Post Production link
    • data-tutorial="tasks" → Tasks link
    • data-tutorial="team" → Team link
    • data-tutorial="assets" → Assets link
  • Added Settings link (visible to all roles)

File: client/src/pages/PostProduction.jsx

  • Added data-tutorial="new-post" to "New Post" button
  • Wrapped filters in <div data-tutorial="filters"> container

Testing Summary

Test 1: Superadmin Login

curl -X POST http://localhost:3001/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"f.mahidi@samayainvest.com","password":"admin123"}'

Success - Returns user with role=superadmin

Test 2: Auth Me (Tutorial Status)

curl -b cookie.txt http://localhost:3001/api/auth/me

Returns:

  • tutorial_completed: 1
  • profileComplete: true
  • brands: [array of brands]

Test 3: Team Visibility (Superadmin)

curl -b cookie.txt http://localhost:3001/api/users/team

Returns all 9 team members

Test 4: Team Visibility (Manager)

Login as manager → GET /api/users/team
Returns only 8 members (filtered by brand overlap)

Test 5: Manager Creates Contributor

curl -b manager-cookie.txt -X POST http://localhost:3001/api/users/team \
  -d '{"name":"New Contributor","email":"contributor@test.com","password":"test123",...}'

Success - Creates user with role=contributor

Test 6: Manager Tries to Create Manager

curl -b manager-cookie.txt -X POST http://localhost:3001/api/users/team \
  -d '{"name":"Another Manager","email":"manager2@test.com","role":"manager",...}'

403 Error: "Managers can only create users with contributor role"

Test 7: Tutorial Toggle

curl -b cookie.txt -X PATCH http://localhost:3001/api/users/me/tutorial \
  -d '{"completed":false}'

Returns: { success: true, tutorial_completed: 0 }

Test 8: Client Build

cd client && npm run build

Built successfully with no errors


Database Schema Changes

Users Table (Updated)

CREATE TABLE users (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  email TEXT NOT NULL UNIQUE,
  password_hash TEXT NOT NULL,
  role TEXT NOT NULL DEFAULT 'contributor',
  avatar TEXT,
  team_member_id INTEGER REFERENCES team_members(id),
  team_role TEXT,
  brands TEXT DEFAULT '[]',
  phone TEXT,
  tutorial_completed INTEGER DEFAULT 0,  -- NEW
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Team Members Table (Updated)

CREATE TABLE team_members (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  email TEXT,
  role TEXT,
  avatar_url TEXT,
  brands TEXT DEFAULT '[]',
  phone TEXT,  -- NEW
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Files Modified

Server

  • server/db.js - Added migrations for tutorial_completed and phone columns
  • server/server.js - Added/modified 5 endpoints

Client

  • client/src/App.jsx - Tutorial integration, profile prompt
  • client/src/pages/Team.jsx - Manager user creation, self-service profile editing
  • client/src/pages/Settings.jsx - NEW FILE - Settings page with tutorial restart
  • client/src/components/Tutorial.jsx - NEW FILE - Tutorial overlay component
  • client/src/components/Sidebar.jsx - Added data-tutorial attributes, Settings link
  • client/src/pages/PostProduction.jsx - Added data-tutorial attributes to toolbar

How to Use

For End Users

As a Manager:

  1. Go to Team page
  2. Click "New Member" button
  3. Fill in name, email, password (optional), team_role, brands, phone
  4. Role is automatically set to "contributor"
  5. Click "Add Member"

As Any User:

  1. Go to Team page
  2. Click "My Profile" button
  3. Edit your name, team_role, brands, phone
  4. Click "Save Profile"

Tutorial:

  • Auto-shows on first login
  • Can be restarted from Settings page
  • Navigate with Next/Back/Skip buttons
  • Click overlay to skip tutorial

For Developers

Test brand filtering:

// As manager with specific brands
const myBrands = ["Samaya Investment", "Hira Cultural District"];
// Will only see users who share at least one brand

Test role enforcement:

// Manager tries to create superadmin
POST /api/users/team { ..., role: 'superadmin' }
// Returns 403: "Managers can only create users with contributor role"

Known Behaviors

  1. Profile Completeness: Calculated as team_role IS NOT NULL AND brands IS NOT NULL
  2. Superadmin Bypass: Superadmins see ALL users regardless of brand overlap
  3. Self-Inclusion: Users always see themselves in the team list
  4. Default Password: New users get "changeme123" if password not provided
  5. Tutorial Targets: Requires elements with data-tutorial attributes to be present in DOM

Future Enhancements

Potential improvements for later:

  • Email notifications when user is created
  • Force password change on first login
  • More granular permissions (per-brand permissions)
  • Tutorial progress tracking (which steps completed)
  • Settings page expansions (notification preferences, theme, language)
  • Brand management UI for non-superadmins

Deployment Notes

  1. Database migrations run automatically on server start
  2. Client requires rebuild: npm run build in client directory
  3. No environment variables changed
  4. Existing data is preserved (users, brands, posts, etc.)
  5. Tutorial shows for existing users on next login (unless manually completed)

Status: All features implemented, tested, and working correctly