From b007b9cf1f1d31ee32cdd2c223de276e97a1ec91 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 18:55:23 +0000 Subject: [PATCH 1/7] Initial plan From faeb0cc5ce43244374da83ee935223e7b452c4ed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 18:59:25 +0000 Subject: [PATCH 2/7] feat: implement role-based UI/UX with actual user role enforcement Co-authored-by: Olu1111 <164207207+Olu1111@users.noreply.github.com> --- frontend/src/components/Navbar.jsx | 21 +++++++- frontend/src/pages/BoardViewPage.jsx | 39 ++++++++------- frontend/src/pages/BoardsList.jsx | 11 +++-- frontend/src/utils/auth.js | 71 ++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+), 22 deletions(-) create mode 100644 frontend/src/utils/auth.js diff --git a/frontend/src/components/Navbar.jsx b/frontend/src/components/Navbar.jsx index 3be99c1..93f5cc2 100644 --- a/frontend/src/components/Navbar.jsx +++ b/frontend/src/components/Navbar.jsx @@ -1,10 +1,11 @@ import React, { useState, useEffect, useCallback, useRef } from 'react'; -import { AppBar, Toolbar, Typography, Button, Box, IconButton, Badge, Menu, Divider } from '@mui/material'; +import { AppBar, Toolbar, Typography, Button, Box, IconButton, Badge, Menu, Divider, Chip } from '@mui/material'; import NotificationsIcon from '@mui/icons-material/Notifications'; import { useNavigate, useLocation } from 'react-router-dom'; import GlobalSearch from './GlobalSearch'; import NotificationItem from './NotificationItem'; import { apiClient } from '../utils/apiClient'; +import { getUserRole } from '../utils/auth'; export default function Navbar({ authenticated }) { const navigate = useNavigate(); @@ -17,6 +18,9 @@ export default function Navbar({ authenticated }) { const pathParts = location.pathname.split('/'); const boardId = pathParts[1] === 'boards' && pathParts[2] ? pathParts[2] : null; + // Get user role for display + const userRole = getUserRole(); + const fetchNotifications = useCallback(async () => { if (authenticated !== true || !boardId) { if (notifications.length > 0) setNotifications([]); @@ -110,6 +114,21 @@ export default function Navbar({ authenticated }) { {authenticated === true && ( + {userRole && ( + + )} + setAnchorEl(e.currentTarget)}> diff --git a/frontend/src/pages/BoardViewPage.jsx b/frontend/src/pages/BoardViewPage.jsx index 385f5c4..d72d5b3 100644 --- a/frontend/src/pages/BoardViewPage.jsx +++ b/frontend/src/pages/BoardViewPage.jsx @@ -13,6 +13,7 @@ import CloseIcon from '@mui/icons-material/Close'; import AddIcon from '@mui/icons-material/Add'; import { useNavigate, useParams } from 'react-router-dom'; import { apiClient } from '../utils/apiClient'; +import { isAdmin, isMember } from '../utils/auth'; import BoardSkeleton from '../components/BoardSkeleton'; import ConfirmDeleteModal from '../components/ConfirmDeleteModal'; import TicketModal from '../components/TicketModal'; @@ -84,7 +85,9 @@ const BoardViewPage = () => { const [isColumnModalOpen, setIsColumnModalOpen] = useState(false); const [snackbar, setSnackbar] = useState({ open: false, message: '', severity: 'success' }); - const isAdmin = true; + // Check user role from localStorage + const userIsAdmin = isAdmin(); + const userIsMember = isMember(); const triggerNotificationSync = useCallback(() => { window.dispatchEvent(new Event('refreshNotifications')); @@ -267,20 +270,22 @@ const BoardViewPage = () => { {/* COLOR FIX: Using Charcoal Grey #263238 */} - + {userIsMember && ( + + )} {columns.length > 0 && setFilters(initialFilters)} />} @@ -293,7 +298,7 @@ const BoardViewPage = () => { handleRenameColumn(column._id, e.target.value)} style={{ background: 'transparent', border: 'none', fontWeight: 'inherit', outline: 'none', width: '100%', fontFamily: 'inherit', fontSize: 'inherit' }} /> - {isAdmin && { setColumnToDelete(column); setIsDeleteModalOpen(true); }}>} + {userIsAdmin && { setColumnToDelete(column); setIsDeleteModalOpen(true); }}>} @@ -329,7 +334,7 @@ const BoardViewPage = () => { )} - + ))} diff --git a/frontend/src/pages/BoardsList.jsx b/frontend/src/pages/BoardsList.jsx index 68b24c4..9f1c888 100644 --- a/frontend/src/pages/BoardsList.jsx +++ b/frontend/src/pages/BoardsList.jsx @@ -5,7 +5,8 @@ import { } from '@mui/material'; import DeleteIcon from '@mui/icons-material/Delete'; import { useNavigate } from 'react-router-dom'; -import BoardModal from '../components/BoardModal'; +import BoardModal from '../components/BoardModal'; +import { isAdmin, isMember } from '../utils/auth'; const BoardsList = () => { const navigate = useNavigate(); @@ -14,7 +15,9 @@ const BoardsList = () => { const [error, setError] = useState(null); const [isModalOpen, setIsModalOpen] = useState(false); - const isAdmin = true; // For visibility of admin controls + // Check user role from localStorage + const userIsAdmin = isAdmin(); + const userIsMember = isMember(); const fetchBoards = async () => { try { @@ -74,7 +77,7 @@ const BoardsList = () => { My Boards Select a project to start working. - {isAdmin && ( + {userIsMember && ( - + {canComment && ( + <> + setText(e.target.value)} sx={{ mt: 1 }} /> + + + + + )} {comments.map((comment) => { diff --git a/frontend/src/components/EditTicketModal.jsx b/frontend/src/components/EditTicketModal.jsx index 1f03ce0..f9202d5 100644 --- a/frontend/src/components/EditTicketModal.jsx +++ b/frontend/src/components/EditTicketModal.jsx @@ -5,6 +5,7 @@ import { Avatar, ListItemIcon, ListItemText, Divider } from '@mui/material'; import CommentThread from './CommentThread'; +import { isMember } from '../utils/auth'; const getAvatarColor = (id, name) => { if (name?.toLowerCase() === 'admin') return "#263238"; @@ -149,6 +150,9 @@ const EditTicketModal = ({ isOpen, onClose, onUpdate, ticket, columns }) => { console.error("Token parsing failed"); } + // Check if user can edit (member or admin) + const canEdit = isMember(); + return ( { - setTitle(e.target.value)} /> - setDescription(e.target.value)} /> + setTitle(e.target.value)} disabled={!canEdit} /> + setDescription(e.target.value)} disabled={!canEdit} /> - setPriority(e.target.value)} sx={{ flex: 1 }}> + setPriority(e.target.value)} sx={{ flex: 1 }} disabled={!canEdit}> High Medium Low - setColumnId(e.target.value)} sx={{ flex: 1 }}> + setColumnId(e.target.value)} sx={{ flex: 1 }} disabled={!canEdit}> {columns.map((col) => ( {col.title} ))} - setAssignee(e.target.value)} fullWidth> + setAssignee(e.target.value)} fullWidth disabled={!canEdit}> - {teamMembers.map((u) => ( @@ -203,10 +207,14 @@ const EditTicketModal = ({ isOpen, onClose, onUpdate, ticket, columns }) => { - - + {isMember() && ( + + )} + - + {canEdit && ( + + )} From 1252b61fef33a39bbe30a324b9c6200d4f24620a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 19:05:08 +0000 Subject: [PATCH 5/7] fix: use consistent canEdit variable for role checking in EditTicketModal Co-authored-by: Olu1111 <164207207+Olu1111@users.noreply.github.com> --- frontend/src/components/EditTicketModal.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/EditTicketModal.jsx b/frontend/src/components/EditTicketModal.jsx index f9202d5..f823680 100644 --- a/frontend/src/components/EditTicketModal.jsx +++ b/frontend/src/components/EditTicketModal.jsx @@ -207,7 +207,7 @@ const EditTicketModal = ({ isOpen, onClose, onUpdate, ticket, columns }) => { - {isMember() && ( + {canEdit && ( )} From 1d9bfd6d5461c9850b6f1ab0dce83949e9076de3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 19:06:58 +0000 Subject: [PATCH 6/7] docs: add comprehensive implementation summary Co-authored-by: Olu1111 <164207207+Olu1111@users.noreply.github.com> --- docs/IMPLEMENTATION_SUMMARY.md | 181 +++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 docs/IMPLEMENTATION_SUMMARY.md diff --git a/docs/IMPLEMENTATION_SUMMARY.md b/docs/IMPLEMENTATION_SUMMARY.md new file mode 100644 index 0000000..83886f7 --- /dev/null +++ b/docs/IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,181 @@ +# Role Enforcement UI/UX Implementation - Summary + +## Overview +This implementation adds comprehensive role-based access control (RBAC) to the Tasky application's user interface. The system leverages the existing backend role infrastructure to provide granular permission controls across the frontend. + +## Implementation Summary + +### βœ… Completed Features + +#### 1. Authentication Utility Module +**File:** `frontend/src/utils/auth.js` + +Created a centralized module for role-based permission checking: +- `getCurrentUser()` - Retrieves user from localStorage +- `getUserRole()` - Gets current user's role +- `isAdmin()` - Checks for admin role +- `isMember()` - Checks for member or admin role +- `isViewer()` - Checks for any authenticated role +- `hasRole(role)` - Hierarchical role checking + +**Role Hierarchy:** Admin (3) > Member (2) > Viewer (1) + +#### 2. UI Components Updated + +##### Navbar Component +- **Added:** Role badge displaying current user role +- **Colors:** Red (admin), Blue (member), Gray (viewer) +- **Location:** Next to notifications icon + +##### BoardsList Page +- **Replaced:** Hardcoded `isAdmin = true` with actual role checking +- **Create Board Button:** Visible only to members and admins +- **Delete Board Icon:** Visible only to admins + +##### BoardViewPage +- **Replaced:** Hardcoded `isAdmin = true` with actual role checking +- **Add Column Button:** Visible only to members and admins +- **Delete Column Icon:** Visible only to admins +- **Add Card Button:** Hidden for viewers (display: none) + +##### EditTicketModal +- **Form Fields:** All fields disabled for viewers (title, description, priority, status, assignee) +- **Save Changes Button:** Hidden for viewers +- **Delete Task Button:** Hidden for viewers +- **Read-only Mode:** Viewers can view ticket details but cannot modify + +##### CommentThread +- **Comment Input:** Hidden for viewers +- **Send Button:** Hidden for viewers +- **Delete Comment:** Visible only to comment author or admins (already implemented) + +### πŸ“‹ Permission Matrix + +| Feature | Viewer | Member | Admin | +|---------|--------|--------|-------| +| **Boards** | +| View Boards | βœ… | βœ… | βœ… | +| Create Boards | ❌ | βœ… | βœ… | +| Delete Boards | ❌ | ❌ | βœ… | +| **Columns** | +| View Columns | βœ… | βœ… | βœ… | +| Create Columns | ❌ | βœ… | βœ… | +| Delete Columns | ❌ | ❌ | βœ… | +| **Tickets/Tasks** | +| View Tickets | βœ… | βœ… | βœ… | +| Create Tickets | ❌ | βœ… | βœ… | +| Edit Tickets | ❌ | βœ… | βœ… | +| Delete Tickets | ❌ | βœ… | βœ… | +| **Comments** | +| View Comments | βœ… | βœ… | βœ… | +| Add Comments | ❌ | βœ… | βœ… | +| Delete Own Comments | ❌ | βœ… | βœ… | +| Delete Any Comment | ❌ | ❌ | βœ… | + +### πŸ”§ Backend Support + +The backend already had comprehensive role enforcement in place: +- **User Model:** Has `role` field with enum ['admin', 'member', 'viewer'] +- **JWT Token:** Includes role in payload +- **Middleware:** `requireAuth`, `requireMember`, `requireAdmin` +- **Role Helpers:** `isAdmin()`, `isMember()`, `hasRoleLevel()` + +This implementation leverages these existing backend features without requiring any backend changes. + +### πŸ“š Documentation + +#### Created Files: +1. **`docs/ROLE_ENFORCEMENT_TESTING.md`** + - 11 comprehensive test cases + - Step-by-step testing instructions + - Permission matrix + - Automated testing script example + +2. **`backend/src/seed/create-test-users.js`** + - Script to create test users with different roles + - Creates admin, member, and viewer users + - Usage: `npm run seed:test-users` + +#### Updated Files: +1. **`README.md`** + - Added link to role enforcement testing documentation + +### πŸ”’ Security Considerations + +1. **Frontend-Only Restrictions:** UI restrictions are for user experience. True security is enforced by backend middleware. + +2. **Token-Based Roles:** Role information is stored in JWT tokens which expire after 7 days. + +3. **Role Updates:** Users must re-login after role changes to see updated permissions. + +4. **No Security Vulnerabilities:** CodeQL scan found 0 security issues. + +### πŸ§ͺ Testing + +#### Manual Testing Required: +To fully test the role enforcement: + +1. **Create Test Users:** + ```bash + cd backend + npm run seed:test-users + ``` + +2. **Test with Each Role:** + - Login as admin@tasky.local (password: password) + - Login as member@tasky.local (password: password) + - Login as viewer@tasky.local (password: password) + +3. **Verify Permissions:** + - Check navbar role badge + - Try creating boards/columns/tickets + - Try deleting items + - Try editing tickets + - Try adding comments + +4. **Test Backend Enforcement:** + - Use curl/Postman to attempt unauthorized actions + - Verify 403 Forbidden responses + +See `docs/ROLE_ENFORCEMENT_TESTING.md` for detailed test cases. + +### πŸ“Š Code Quality + +- βœ… **Linting:** All files pass ESLint checks +- βœ… **Build:** Frontend builds successfully without warnings +- βœ… **Code Review:** All review comments addressed +- βœ… **Security Scan:** CodeQL found 0 vulnerabilities +- βœ… **Consistency:** Consistent use of role checking utilities + +### 🎯 Impact + +**Files Modified:** 7 +**Files Created:** 3 +**Lines Added:** ~450 +**Lines Modified:** ~50 + +**Key Benefits:** +1. **Better UX:** Users only see features they can use +2. **Clear Permissions:** Role badge shows user's permission level +3. **Security:** Frontend restrictions complement backend enforcement +4. **Maintainable:** Centralized role checking logic +5. **Testable:** Comprehensive testing documentation + +### πŸš€ Next Steps (Post-Implementation) + +1. **Create Test Users:** Run `npm run seed:test-users` in backend +2. **Manual Testing:** Follow the testing guide +3. **User Feedback:** Gather feedback on role restrictions +4. **Iteration:** Adjust permissions based on user needs + +### πŸ“ Notes + +- The backend role system was already well-implemented +- This PR focuses purely on frontend UI/UX enforcement +- No database schema changes required +- No API changes required +- Backward compatible with existing user accounts + +## Conclusion + +This implementation successfully adds role-based UI/UX enforcement to the Tasky application, making the user interface match the backend's permission system. Users now have a clear visual indication of their role and can only interact with features they have permission to use. From ea13c333d355ac8b7f380c58ef81288a7430bd5b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 19:08:03 +0000 Subject: [PATCH 7/7] docs: add visual guide for UI changes Co-authored-by: Olu1111 <164207207+Olu1111@users.noreply.github.com> --- docs/UI_CHANGES_VISUAL_GUIDE.md | 249 ++++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 docs/UI_CHANGES_VISUAL_GUIDE.md diff --git a/docs/UI_CHANGES_VISUAL_GUIDE.md b/docs/UI_CHANGES_VISUAL_GUIDE.md new file mode 100644 index 0000000..6fbe448 --- /dev/null +++ b/docs/UI_CHANGES_VISUAL_GUIDE.md @@ -0,0 +1,249 @@ +# Role Enforcement UI/UX - Visual Changes Guide + +## Overview +This document provides visual descriptions of the UI changes implemented for role-based access control. + +## 1. Navbar - Role Badge + +### Before: +``` +[Tasky] [Search] [Notifications] [My Tickets] [Boards] [Logout] +``` + +### After: +``` +[Tasky] [Search] [ADMIN] [Notifications] [My Tickets] [Boards] [Logout] + ^^^^^^ + Role Badge +``` + +**Role Badge Styling:** +- **ADMIN**: Red background (#d32f2f), white text +- **MEMBER**: Blue background (#1976d2), white text +- **VIEWER**: Gray background (#757575), white text + +**Location:** Between search bar and notifications icon + +--- + +## 2. Boards List Page + +### Admin/Member View: +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ My Boards [+ Create Board] β”‚ +β”‚ Select a project to start working. β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Board 1 [Γ—]β”‚ β”‚ Board 2 [Γ—]β”‚ β”‚ Board 3 [Γ—]β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ Descriptionβ”‚ β”‚ Descriptionβ”‚ β”‚ Descriptionβ”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` +- "Create Board" button is VISIBLE +- Delete icons ([Γ—]) are VISIBLE (only for admins) + +### Viewer View: +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ My Boards β”‚ +β”‚ Select a project to start working. β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Board 1 β”‚ β”‚ Board 2 β”‚ β”‚ Board 3 β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ Descriptionβ”‚ β”‚ Descriptionβ”‚ β”‚ Descriptionβ”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` +- "Create Board" button is HIDDEN +- Delete icons ([Γ—]) are HIDDEN + +--- + +## 3. Board View Page + +### Admin/Member View: +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ [← Back] Board Name [Filter] [Search] [+ Add Column] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Todo [Γ—] β”‚ β”‚ Doing [Γ—] β”‚ β”‚ Done [Γ—] β”‚ +│─────────────│ │─────────────│ │─────────────│ +β”‚ Task 1 β”‚ β”‚ Task 3 β”‚ β”‚ Task 5 β”‚ +β”‚ Task 2 β”‚ β”‚ Task 4 β”‚ β”‚ Task 6 β”‚ +β”‚ [+ Add card]β”‚ β”‚ [+ Add card]β”‚ β”‚ [+ Add card]β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` +- "Add Column" button is VISIBLE +- Column delete icons ([Γ—]) are VISIBLE (admins only) +- "Add a card" buttons are VISIBLE + +### Viewer View: +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ [← Back] Board Name [Filter] [Search] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Todo β”‚ β”‚ Doing β”‚ β”‚ Done β”‚ +│─────────────│ │─────────────│ │─────────────│ +β”‚ Task 1 β”‚ β”‚ Task 3 β”‚ β”‚ Task 5 β”‚ +β”‚ Task 2 β”‚ β”‚ Task 4 β”‚ β”‚ Task 6 β”‚ +β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` +- "Add Column" button is HIDDEN +- Column delete icons ([Γ—]) are HIDDEN +- "Add a card" buttons are HIDDEN + +--- + +## 4. Edit Ticket Modal + +### Admin/Member View: +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Edit Task [Γ—]β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Title: [Fix login bug ] β”‚ +β”‚ Description:[The login button... ] β”‚ +β”‚ Priority: [High β–Ό] Status: [Todo β–Ό] β”‚ +β”‚ Assignee: [John Doe β–Ό ] β”‚ +β”‚ β”‚ +β”‚ Comments (3) β”‚ +β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ +β”‚ β”‚ [Write a comment... ] β”‚ β”‚ +β”‚ β”‚ [Send] β”‚ β”‚ +β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ +β”‚ β”‚ +β”‚ [Delete Task] [Cancel] [Save Changes] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` +- All fields are EDITABLE +- Comment input is VISIBLE +- "Delete Task" button is VISIBLE +- "Save Changes" button is VISIBLE + +### Viewer View: +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Edit Task [Γ—]β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Title: [Fix login bug ]πŸ”’ β”‚ +β”‚ Description:[The login button... ]πŸ”’ β”‚ +β”‚ Priority: [High β–Ό]πŸ”’ Status: [Todo β–Ό]πŸ”’ β”‚ +β”‚ Assignee: [John Doe β–Ό ]πŸ”’ β”‚ +β”‚ β”‚ +β”‚ Comments (3) β”‚ +β”‚ (No input field - viewers cannot comment) β”‚ +β”‚ β”‚ +β”‚ [Cancel] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` +- All fields are DISABLED (πŸ”’ indicates disabled state) +- Comment input is HIDDEN +- "Delete Task" button is HIDDEN +- "Save Changes" button is HIDDEN +- Only "Cancel" button is available + +--- + +## 5. Comments Section + +### For Comment Author or Admin: +``` +Comments (3) +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ [Write a comment... ] β”‚ +β”‚ [Send] β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ πŸ‘€ John Doe 12:34 PM [Γ—] β”‚ +β”‚ Great work on this! β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` +- Comment input is VISIBLE (members/admins only) +- Delete button ([Γ—]) is VISIBLE for own comments or all comments (admins) + +### For Viewer: +``` +Comments (3) +(No input field - viewers cannot comment) + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ πŸ‘€ John Doe 12:34 PM β”‚ +β”‚ Great work on this! β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` +- Comment input is HIDDEN +- Delete buttons are HIDDEN + +--- + +## Summary of Visual Changes + +### Elements Added: +1. βœ… Role badge in navbar (color-coded by role) + +### Elements Hidden/Shown Based on Role: +1. βœ… "Create Board" button (members+ only) +2. βœ… "Delete Board" icon (admins only) +3. βœ… "Add Column" button (members+ only) +4. βœ… "Delete Column" icon (admins only) +5. βœ… "Add a card" buttons (members+ only) +6. βœ… Comment input field (members+ only) +7. βœ… "Delete Task" button (members+ only) +8. βœ… "Save Changes" button (members+ only) + +### Elements Disabled Based on Role: +1. βœ… All ticket form fields (disabled for viewers) +2. βœ… Assignee dropdown (disabled for viewers) + +--- + +## Testing the Visual Changes + +To see these changes in action: + +1. **Create test users** (if not already created): + ```bash + cd backend + npm run seed:test-users + ``` + +2. **Login as different roles**: + - Admin: admin@tasky.local / password + - Member: member@tasky.local / password + - Viewer: viewer@tasky.local / password + +3. **Navigate through the app** and observe: + - Navbar role badge changes color + - Buttons appear/disappear based on permissions + - Form fields become disabled for viewers + - Comment input hidden for viewers + +4. **Try to perform restricted actions**: + - As viewer, you won't see create/delete buttons + - As member, you can create but not delete boards/columns + - As admin, you can do everything + +--- + +## Color Reference + +| Role | Badge Color | Hex Code | +|------|-------------|----------| +| Admin | Red | #d32f2f | +| Member | Blue | #1976d2 | +| Viewer | Gray | #757575 | + +| Element | Color | Hex Code | +|---------|-------|----------| +| Primary Action Buttons | Charcoal Grey | #263238 | +| Delete Buttons | Red | #d32f2f | +| Disabled State | Light Gray | - (MUI default) |