Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"no-shadow": 0,
"no-unused-expressions": 0,
"react/require-default-props": 0,
"import/prefer-default-export": 0
"import/prefer-default-export": 0,
"react/no-unstable-nested-components": 0
}
}
12 changes: 8 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@
rel="stylesheet"
/> -->

<link href="https://fonts.googleapis.com/css2?family=PT+Serif:wght@400;700&display=swap" rel="stylesheet">

<link
href="https://fonts.googleapis.com/css2?family=PT+Serif:wght@400;700&display=swap"
rel="stylesheet"
/>
</head>
<body class="dark:bg-dark-frame-bg">
<div id="tree"></div>
Expand Down Expand Up @@ -90,8 +92,10 @@
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"
rel="stylesheet"
/> -->
<link href="https://fonts.googleapis.com/css2?family=PT+Serif:wght@400;700&display=swap" rel="stylesheet">

<link
href="https://fonts.googleapis.com/css2?family=PT+Serif:wght@400;700&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div id="tree"></div>
Expand Down
4 changes: 2 additions & 2 deletions public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,6 @@
"Provide Quantity range between 1-2": "Fournir une gamme de quantité comprise entre 1-2",
"Provide Professional_Skills range between 1-2": "Fournir une gamme de compétences professionnelles comprise entre 1-2",
"Sprint Ratings": "Sprint Notations",
"Please wait to be added to a program or cohort":"Veuillez attendre d'être ajouté à un programme ou à une cohorte",
"Enter all the required information":"Entrez toutes les informations requises"
"Please wait to be added to a program or cohort": "Veuillez attendre d'être ajouté à un programme ou à une cohorte",
"Enter all the required information": "Entrez toutes les informations requises"
}
20 changes: 10 additions & 10 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ function App() {
return (
<div className="min-h-screen">
<TicketsProvider>
<TraineesProvider>
<Router>
<ScrollToTop>
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/*" element={<MainRoutes />} />
</Routes>
</ScrollToTop>
</Router>
</TraineesProvider>
<TraineesProvider>
<Router>
<ScrollToTop>
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/*" element={<MainRoutes />} />
</Routes>
</ScrollToTop>
</Router>
</TraineesProvider>
</TicketsProvider>
</div>
);
Expand Down
32 changes: 32 additions & 0 deletions src/Mutations/ActionDropdownCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import ActionDropdown from '../components/ActionDropdown';

interface ActionDropdownCellProps {
row: {
original: any;
};
onView: (ticket: any) => void;
onEdit?: (id: string) => void;
onDelete?: (id: string) => void;
canEditDelete: boolean;
}

function ActionDropdownCell({
row,
onView,
onEdit,
onDelete,
canEditDelete,
}: ActionDropdownCellProps) {
return (
<ActionDropdown
onView={() => onView(row.original)}
onEdit={canEditDelete ? () => onEdit?.(row.original.id) : undefined}
onDelete={canEditDelete ? () => onDelete?.(row.original.id) : undefined}
canEditDelete={canEditDelete}
id={row.original.id}
/>
);
}

export default ActionDropdownCell;
2 changes: 1 addition & 1 deletion src/Mutations/User.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,4 @@ export const DROP_TTL_USER = gql`
dropTTLUser(email: $email, reason: $reason)
}
`;
export default GET_PROFILE;
export default GET_PROFILE;
4 changes: 2 additions & 2 deletions src/Mutations/help.mutation.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { gql } from '@apollo/client';

const CREATE_TICKET = gql`
mutation CreateTicket($subject: String!, $message: String!) {
createTicket(subject: $subject, message: $message) {
mutation CreateTicket($subject: String!, $message: String!, $assignee: ID!) {
createTicket(subject: $subject, message: $message, assignee: $assignee) {
responseMsg
}
}
Expand Down
137 changes: 137 additions & 0 deletions src/components/ActionDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import React, { useState, useEffect, useRef } from 'react';
import {
FaEllipsisV,
FaEye,
FaEdit,
FaTrashAlt,
FaClipboard,
} from 'react-icons/fa';
import { toast } from 'react-toastify';

interface ActionDropdownProps {
onView: () => void;
onEdit?: () => void;
onDelete?: () => void;
canEditDelete: boolean;
id?: string;
}

function ActionDropdown({
onView,
onEdit,
onDelete,
canEditDelete,
id,
}: ActionDropdownProps) {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);

const toggleDropdown = () => setIsOpen(!isOpen);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setIsOpen(false);
}
};

if (isOpen) {
document.addEventListener('mousedown', handleClickOutside);
} else {
document.removeEventListener('mousedown', handleClickOutside);
}

return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [isOpen]);

const copyToClipboard = (text: any) => {
navigator.clipboard
.writeText(text)
.then(() => {
toast.success('ID copied to clipboard!');
})
.catch((err) => {
toast.error(`Failed to copy: ${err}`);
});
};

return (
<div className="relative" ref={dropdownRef}>
{/* Hide ellipsis icon if the dropdown is open */}
{!isOpen && (
<button
type="button"
aria-label="Open actions menu"
className="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
onClick={toggleDropdown}
>
<FaEllipsisV className="text-lg" />
</button>
)}

{isOpen && (
<div className="absolute right-0 z-10 w-48 mt-2 bg-white border border-gray-200 rounded-md shadow-lg">
<button
type="button"
aria-label="View item"
onClick={() => {
onView();
setIsOpen(false);
}}
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"
>
<FaEye className="mr-2" />
View
</button>
{canEditDelete && (
<>
<button
type="button"
aria-label="Edit item"
onClick={() => {
onEdit?.();
setIsOpen(false);
}}
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"
>
<FaEdit className="mr-2" />
Edit
</button>
<button
type="button"
aria-label="Delete item"
onClick={() => {
onDelete?.();
setIsOpen(false);
}}
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"
>
<FaTrashAlt className="mr-2" />
Delete
</button>
</>
)}
<button
type="button"
aria-label="Copy ID"
onClick={() => {
copyToClipboard(id);
setIsOpen(false);
}}
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"
>
<FaClipboard className="mr-2" />
Copy ID
</button>
</div>
)}
</div>
);
}

export default ActionDropdown;
5 changes: 1 addition & 4 deletions src/components/AttendanceStatistics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,7 @@ function BarChart() {

return (
<div className="bg-white dark:bg-dark-bg shadow-lg px-5 py-8 rounded-md w-full font-serif">
<div className="">
hello

</div>
<div className="">hello</div>
</div>
);
}
Expand Down
17 changes: 9 additions & 8 deletions src/components/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,9 @@ const Calendar = () => {
<>
{/* =========================== Start:: RegisterTraineeModel =========================== */}
<div
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'
}`}
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'
}`}
>
<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">
<div className="card-title w-full flex flex-wrap justify-center items-center ">
Expand Down Expand Up @@ -155,9 +156,9 @@ const Calendar = () => {
value={newEvent.hostName}
onChange /* istanbul ignore next */={(e) =>
/* istanbul ignore next */ setNewEvent({
...newEvent,
hostName: e.target.value,
})
...newEvent,
hostName: e.target.value,
})
}
/>
</div>
Expand All @@ -172,9 +173,9 @@ const Calendar = () => {
selected={newEvent.start}
onChange /* istanbul ignore next */={(start: any) =>
/* istanbul ignore next */ setNewEvent({
...newEvent,
start,
})
...newEvent,
start,
})
}
/>
</div>
Expand Down
64 changes: 64 additions & 0 deletions src/components/ConfirmationModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* eslint-disable react/function-component-definition */
import React, { useState } from 'react';
import { toast } from 'react-toastify';

interface ConfirmationModalProps {
isOpen: boolean;
onConfirm: () => void;
onCancel: () => void;
message: string;
}

const ConfirmationModal: React.FC<ConfirmationModalProps> = ({
isOpen,
onConfirm,
onCancel,
message,
}) => {
const [loading, setLoading] = useState(false);

if (!isOpen) return null;

const handleConfirm = async () => {
setLoading(true);
try {
onConfirm();
} catch (error) {
toast.error('Failed to confirm action. Please try again.');
} finally {
setLoading(false);
}
};

return (
<div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50">
<div className="w-full max-w-sm p-6 bg-white rounded-lg shadow-lg dark:bg-gray-800 dark:shadow-gray-700">
<h2 className="mb-4 text-2xl font-bold text-gray-900 dark:text-gray-100">
Confirm Action
</h2>
<p className="mb-4 text-gray-700 dark:text-gray-300">{message}</p>
<div className="flex justify-end space-x-4">
<button
type="button"
onClick={onCancel}
className="px-4 py-2 text-white bg-gray-500 rounded hover:bg-gray-600 focus:outline-none focus:ring-2 focus:ring-gray-400 dark:bg-gray-600 dark:hover:bg-gray-700 dark:focus:ring-gray-500"
>
Cancel
</button>
<button
onClick={handleConfirm}
type="button"
className={`px-4 py-2 text-white rounded hover:bg-red-600 focus:outline-none focus:ring-2 ${
loading ? 'bg-red-400 cursor-not-allowed' : 'bg-red-500'
} dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-500`}
disabled={loading}
>
{loading ? 'Processing...' : 'Confirm'}
</button>
</div>
</div>
</div>
);
};

export default ConfirmationModal;
Loading
Loading