Skip to content

Commit cdb4053

Browse files
fix tickets-crud that was introduced in issues 242 (#495)
-Admins and Coordinators will be able to create tickets -Traineess will be able to see tickets assigned to them -Also Admins and Admins can also perform CRUD operations on Tickets
1 parent 1393242 commit cdb4053

File tree

97 files changed

+2034
-1017
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+2034
-1017
lines changed

.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"no-shadow": 0,
4242
"no-unused-expressions": 0,
4343
"react/require-default-props": 0,
44-
"import/prefer-default-export": 0
44+
"import/prefer-default-export": 0,
45+
"react/no-unstable-nested-components": 0
4546
}
4647
}

index.html

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@
4141
rel="stylesheet"
4242
/> -->
4343

44-
<link href="https://fonts.googleapis.com/css2?family=PT+Serif:wght@400;700&display=swap" rel="stylesheet">
45-
44+
<link
45+
href="https://fonts.googleapis.com/css2?family=PT+Serif:wght@400;700&display=swap"
46+
rel="stylesheet"
47+
/>
4648
</head>
4749
<body class="dark:bg-dark-frame-bg">
4850
<div id="tree"></div>
@@ -90,8 +92,10 @@
9092
href="https://fonts.googleapis.com/css2?family=Inria+Serif:ital@1&family=Lexend+Deca:wght@600&family=Open+Sans:wght@300;400;600;700;800&display=swap"
9193
rel="stylesheet"
9294
/> -->
93-
<link href="https://fonts.googleapis.com/css2?family=PT+Serif:wght@400;700&display=swap" rel="stylesheet">
94-
95+
<link
96+
href="https://fonts.googleapis.com/css2?family=PT+Serif:wght@400;700&display=swap"
97+
rel="stylesheet"
98+
/>
9599
</head>
96100
<body>
97101
<div id="tree"></div>

public/locales/fr/translation.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,6 @@
463463
"Provide Quantity range between 1-2": "Fournir une gamme de quantité comprise entre 1-2",
464464
"Provide Professional_Skills range between 1-2": "Fournir une gamme de compétences professionnelles comprise entre 1-2",
465465
"Sprint Ratings": "Sprint Notations",
466-
"Please wait to be added to a program or cohort":"Veuillez attendre d'être ajouté à un programme ou à une cohorte",
467-
"Enter all the required information":"Entrez toutes les informations requises"
466+
"Please wait to be added to a program or cohort": "Veuillez attendre d'être ajouté à un programme ou à une cohorte",
467+
"Enter all the required information": "Entrez toutes les informations requises"
468468
}

src/App.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@ function App() {
1212
return (
1313
<div className="min-h-screen">
1414
<TicketsProvider>
15-
<TraineesProvider>
16-
<Router>
17-
<ScrollToTop>
18-
<Routes>
19-
<Route path="/" element={<LandingPage />} />
20-
<Route path="/*" element={<MainRoutes />} />
21-
</Routes>
22-
</ScrollToTop>
23-
</Router>
24-
</TraineesProvider>
15+
<TraineesProvider>
16+
<Router>
17+
<ScrollToTop>
18+
<Routes>
19+
<Route path="/" element={<LandingPage />} />
20+
<Route path="/*" element={<MainRoutes />} />
21+
</Routes>
22+
</ScrollToTop>
23+
</Router>
24+
</TraineesProvider>
2525
</TicketsProvider>
2626
</div>
2727
);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from 'react';
2+
import ActionDropdown from '../components/ActionDropdown';
3+
4+
interface ActionDropdownCellProps {
5+
row: {
6+
original: any;
7+
};
8+
onView: (ticket: any) => void;
9+
onEdit?: (id: string) => void;
10+
onDelete?: (id: string) => void;
11+
canEditDelete: boolean;
12+
}
13+
14+
function ActionDropdownCell({
15+
row,
16+
onView,
17+
onEdit,
18+
onDelete,
19+
canEditDelete,
20+
}: ActionDropdownCellProps) {
21+
return (
22+
<ActionDropdown
23+
onView={() => onView(row.original)}
24+
onEdit={canEditDelete ? () => onEdit?.(row.original.id) : undefined}
25+
onDelete={canEditDelete ? () => onDelete?.(row.original.id) : undefined}
26+
canEditDelete={canEditDelete}
27+
id={row.original.id}
28+
/>
29+
);
30+
}
31+
32+
export default ActionDropdownCell;

src/Mutations/User.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,4 @@ export const DROP_TTL_USER = gql`
131131
dropTTLUser(email: $email, reason: $reason)
132132
}
133133
`;
134-
export default GET_PROFILE;
134+
export default GET_PROFILE;

src/Mutations/help.mutation.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { gql } from '@apollo/client';
22

33
const CREATE_TICKET = gql`
4-
mutation CreateTicket($subject: String!, $message: String!) {
5-
createTicket(subject: $subject, message: $message) {
4+
mutation CreateTicket($subject: String!, $message: String!, $assignee: ID!) {
5+
createTicket(subject: $subject, message: $message, assignee: $assignee) {
66
responseMsg
77
}
88
}

src/components/ActionDropdown.tsx

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import React, { useState, useEffect, useRef } from 'react';
2+
import {
3+
FaEllipsisV,
4+
FaEye,
5+
FaEdit,
6+
FaTrashAlt,
7+
FaClipboard,
8+
} from 'react-icons/fa';
9+
import { toast } from 'react-toastify';
10+
11+
interface ActionDropdownProps {
12+
onView: () => void;
13+
onEdit?: () => void;
14+
onDelete?: () => void;
15+
canEditDelete: boolean;
16+
id?: string;
17+
}
18+
19+
function ActionDropdown({
20+
onView,
21+
onEdit,
22+
onDelete,
23+
canEditDelete,
24+
id,
25+
}: ActionDropdownProps) {
26+
const [isOpen, setIsOpen] = useState(false);
27+
const dropdownRef = useRef<HTMLDivElement>(null);
28+
29+
const toggleDropdown = () => setIsOpen(!isOpen);
30+
31+
useEffect(() => {
32+
const handleClickOutside = (event: MouseEvent) => {
33+
if (
34+
dropdownRef.current &&
35+
!dropdownRef.current.contains(event.target as Node)
36+
) {
37+
setIsOpen(false);
38+
}
39+
};
40+
41+
if (isOpen) {
42+
document.addEventListener('mousedown', handleClickOutside);
43+
} else {
44+
document.removeEventListener('mousedown', handleClickOutside);
45+
}
46+
47+
return () => {
48+
document.removeEventListener('mousedown', handleClickOutside);
49+
};
50+
}, [isOpen]);
51+
52+
const copyToClipboard = (text: any) => {
53+
navigator.clipboard
54+
.writeText(text)
55+
.then(() => {
56+
toast.success('ID copied to clipboard!');
57+
})
58+
.catch((err) => {
59+
toast.error(`Failed to copy: ${err}`);
60+
});
61+
};
62+
63+
return (
64+
<div className="relative" ref={dropdownRef}>
65+
{/* Hide ellipsis icon if the dropdown is open */}
66+
{!isOpen && (
67+
<button
68+
type="button"
69+
aria-label="Open actions menu"
70+
className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
71+
onClick={toggleDropdown}
72+
>
73+
<FaEllipsisV className="text-lg" />
74+
</button>
75+
)}
76+
77+
{isOpen && (
78+
<div className="absolute right-0 z-10 w-48 mt-2 bg-white border border-gray-200 rounded-md shadow-lg">
79+
<button
80+
type="button"
81+
aria-label="View item"
82+
onClick={() => {
83+
onView();
84+
setIsOpen(false);
85+
}}
86+
className="flex items-center w-full px-4 py-2 text-sm text-blue-600 hover:bg-blue-100 dark:text-blue-400 dark:hover:bg-blue-700"
87+
>
88+
<FaEye className="mr-2" />
89+
View
90+
</button>
91+
{canEditDelete && (
92+
<>
93+
<button
94+
type="button"
95+
aria-label="Edit item"
96+
onClick={() => {
97+
onEdit?.();
98+
setIsOpen(false);
99+
}}
100+
className="flex items-center w-full px-4 py-2 text-sm text-yellow-600 hover:bg-yellow-100 dark:text-yellow-400 dark:hover:bg-yellow-700"
101+
>
102+
<FaEdit className="mr-2" />
103+
Edit
104+
</button>
105+
<button
106+
type="button"
107+
aria-label="Delete item"
108+
onClick={() => {
109+
onDelete?.();
110+
setIsOpen(false);
111+
}}
112+
className="flex items-center w-full px-4 py-2 text-sm text-red-600 hover:bg-red-100 dark:text-red-400 dark:hover:bg-red-700"
113+
>
114+
<FaTrashAlt className="mr-2" />
115+
Delete
116+
</button>
117+
</>
118+
)}
119+
<button
120+
type="button"
121+
aria-label="Copy ID"
122+
onClick={() => {
123+
copyToClipboard(id);
124+
setIsOpen(false);
125+
}}
126+
className="flex items-center w-full px-4 py-2 text-sm text-gray-600 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
127+
>
128+
<FaClipboard className="mr-2" />
129+
Copy ID
130+
</button>
131+
</div>
132+
)}
133+
</div>
134+
);
135+
}
136+
137+
export default ActionDropdown;

src/components/AttendanceStatistics.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,7 @@ function BarChart() {
4646

4747
return (
4848
<div className="bg-white dark:bg-dark-bg shadow-lg px-5 py-8 rounded-md w-full font-serif">
49-
<div className="">
50-
hello
51-
52-
</div>
49+
<div className="">hello</div>
5350
</div>
5451
);
5552
}

src/components/Calendar.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,9 @@ const Calendar = () => {
108108
<>
109109
{/* =========================== Start:: RegisterTraineeModel =========================== */}
110110
<div
111-
className={`font-serif h-screen w-screen bg-black bg-opacity-30 backdrop-blur-sm fixed top-0 left-0 z-20 flex items-center justify-center px-4 ${addEventModel === true ? 'block' : 'hidden'
112-
}`}
111+
className={`font-serif h-screen w-screen bg-black bg-opacity-30 backdrop-blur-sm fixed top-0 left-0 z-20 flex items-center justify-center px-4 ${
112+
addEventModel === true ? 'block' : 'hidden'
113+
}`}
113114
>
114115
<div className="bg-indigo-100 dark:bg-dark-bg w-full sm:w-3/4 md:w-1/2 xl:w-4/12 rounded-lg p-4 pb-8">
115116
<div className="card-title w-full flex flex-wrap justify-center items-center ">
@@ -155,9 +156,9 @@ const Calendar = () => {
155156
value={newEvent.hostName}
156157
onChange /* istanbul ignore next */={(e) =>
157158
/* istanbul ignore next */ setNewEvent({
158-
...newEvent,
159-
hostName: e.target.value,
160-
})
159+
...newEvent,
160+
hostName: e.target.value,
161+
})
161162
}
162163
/>
163164
</div>
@@ -172,9 +173,9 @@ const Calendar = () => {
172173
selected={newEvent.start}
173174
onChange /* istanbul ignore next */={(start: any) =>
174175
/* istanbul ignore next */ setNewEvent({
175-
...newEvent,
176-
start,
177-
})
176+
...newEvent,
177+
start,
178+
})
178179
}
179180
/>
180181
</div>

0 commit comments

Comments
 (0)