Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

# production
/build
/dist

# misc
.DS_Store
Expand Down
Binary file added public/assets/icons/Uncheck-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/icons/delete-icon-24.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/icons/edit-icon-24.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/assets/icons/info.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 2 additions & 13 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import PartnerAdvertisements from 'components/SignupSheet/PartnerAdvertisements'
import Duties from "./pages/Duties/Duties";
import DutyEditor from "./pages/Duties/DutyEditor";
import ReviewReportPage from "./pages/Reviews/ReviewReportPage";
import AssignmentParticipants from "./pages/AssignmentParticipants/AssignmentParticipants";
function App() {
const router = createBrowserRouter([
{
Expand Down Expand Up @@ -227,19 +228,7 @@ function App() {

{
path: "assignments/edit/:assignmentId/participants",
element: <Participants type="student_tasks" id={1} />,
children: [
{
path: "new",
element: <ParticipantEditor mode="create" type="assignments" />,
loader: loadParticipantDataRolesAndInstitutions,
},
{
path: "edit/:id",
element: <ParticipantEditor mode="update" type="assignments" />,
loader: loadParticipantDataRolesAndInstitutions,
},
],
element: <AssignmentParticipants />,
},

{
Expand Down
15 changes: 2 additions & 13 deletions src/components/Modals/ExportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { useEffect, useState, memo, useCallback } from "react";
import { Modal, Button, Form, Row, Col, OverlayTrigger, Tooltip } from "react-bootstrap";
import useAPI from "../../hooks/useAPI";
import { HttpMethod } from "../../utils/httpMethods";
import { publicUrl } from "../../utils/publicUrl";

/* =============================================================================
Shared visual style — same as CreateTeams.tsx
Expand All @@ -26,19 +27,7 @@ const TABLE_TEXT: React.CSSProperties = {
Icon utilities — same pattern as Import modal
============================================================================= */

const getBaseUrl = (): string => {
if (typeof document !== 'undefined') {
const base = document.querySelector('base[href]') as HTMLBaseElement | null;
if (base?.href) return base.href.replace(/\/$/, '');
}
const fromGlobal = (globalThis as any)?.__BASE_URL__;
if (typeof fromGlobal === 'string' && fromGlobal) return fromGlobal.replace(/\/$/, '');
const fromProcess =
(typeof process !== 'undefined' && (process as any)?.env?.PUBLIC_URL) || '';
return String(fromProcess).replace(/\/$/, '');
};

const assetUrl = (rel: string) => `${getBaseUrl()}/${rel.replace(/^\//, '')}`;
const assetUrl = (rel: string) => publicUrl(rel.replace(/^\//, ''));



Expand Down
20 changes: 2 additions & 18 deletions src/components/Modals/ImportModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import useAPI from "../../hooks/useAPI";
import { HttpMethod } from "../../utils/httpMethods";
import PreviewTable from "../Table/Table";
import { ColumnDef } from "@tanstack/react-table";
import { publicUrl } from "../../utils/publicUrl";

/* ----------------------------------------
* Shared text styles for consistency
Expand All @@ -39,24 +40,7 @@ const TABLE_TEXT: React.CSSProperties = {
* Icon utilities — used for tooltip icons
* ---------------------------------------- */

/** Helper to resolve asset URLs correctly even under nested routes */
const getBaseUrl = (): string => {
if (typeof document !== "undefined") {
const base = document.querySelector("base[href]") as HTMLBaseElement | null;
if (base?.href) return base.href.replace(/\/$/, "");
}

const fromGlobal = (globalThis as any)?.__BASE_URL__;
if (typeof fromGlobal === "string") return fromGlobal.replace(/\/$/, "");

const fromProcess =
(typeof process !== "undefined" && (process as any)?.env?.PUBLIC_URL) || "";

return String(fromProcess).replace(/\/$/, "");
};

/** Helper for converting relative asset paths to usable URLs */
const assetUrl = (rel: string) => `${getBaseUrl()}/${rel.replace(/^\//, "")}`;
const assetUrl = (rel: string) => publicUrl(rel.replace(/^\//, ""));

/** Asset map */
const ICONS = {
Expand Down
280 changes: 280 additions & 0 deletions src/pages/AssignmentParticipants/AssignmentParticipants.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
/* Container and Header */
.assignment-participants-container {
padding: 1.5rem;
border-radius: 0.5rem;
width: 100%;
max-width: 100%;
margin: 1rem auto;
}

.assignment-participants-header {
font-size: 1.5rem;
font-weight: bold;
color: #333333;
margin-bottom: 1.5rem;
}

.section-label {
display: block;
font-weight: bold;
font-size: 1rem;
color: #333;
margin-bottom: 0.5rem;
}

/* Search Filter Section */
.search-filter-section {
display: flex;
align-items: flex-start;
flex-wrap: nowrap;
gap: 1rem;
margin-bottom: 1rem;
}

.search-input {
color: #333;
font-size: 0.95rem;
font-weight: 500;
border: 1px solid #2563eb;
border-radius: 0.5rem;
background-color: #ffffff;
height: 42px;
width: 100%;
max-width: 440px;
flex: 1 1 320px;
box-sizing: border-box;
cursor: text;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
margin: 0;
}

.search-input::placeholder {
color: #aaa;
font-weight: 400;
}

.filter-select {
color: #333;
font-size: 0.95rem;
font-weight: 500;
padding: 0 1rem;
height: 42px;
width: 180px;
min-width: 180px;
flex: 0 0 180px;
border: 1px solid #2563eb;
border-radius: 0.5rem;
background-color: #ffffff;
cursor: pointer;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
margin: 0;
}

.filter-select:hover {
/* Slightly darker shade for hover */
border-color: #1d4ed8;
/* Soft blue glow */
box-shadow: 0 0 5px rgba(29, 78, 216, 0.4);
}

.filter-select:focus {
outline: none;
border-color: #1d4ed8;
/* Blue focus ring */
box-shadow: 0 0 0 3px rgba(29, 78, 216, 0.3);
}

.filter-select option {
font-size: 1rem;
padding: 0.5rem;
}

/* Add User Section */
.add-user-section {
display: flex;
width: 100%;
justify-content: space-between;
flex-wrap: wrap;
align-content: center;
gap: 1rem;
margin-bottom: 0.75rem;
border-bottom: 1px solid #e5e7eb;
}

.user-permissions {
display: flex;
gap: 1rem;
}

.permission-yes,
.permission-no {
font-size: 1.5rem;
/* Increase icon size */
display: inline-flex;
align-items: center;
justify-content: center;
}

.user-input {
flex: 1;
min-width: 400px;
height: 42px;
border: 1px solid #ccc;
border-radius: 0.25rem;
font-size: 16px;
box-sizing: border-box;
}

.user-input::placeholder {
color: #aaa;
font-weight: 400;
}

.add-user-button {
color: #10b981;
min-width: 90px;
height: 42px;
/* Green tone for positive action */
font-weight: 600;
cursor: pointer;
background-color: transparent;
border: 1px solid transparent;
padding: 0.4em 0.8em;
border-radius: 4px;
border-color: #10d6a6;
transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;
}

.add-user-button:hover {
color: #059669;
/* Darker green shade for hover effect */
background-color: rgba(16, 185, 129, 0.1);
border-color: #10b981;
text-decoration: none;
}

.add-user-button:focus {
/* Focus ring for accessibility */
outline: none;
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.4);
}

/* Role Radio Group Styling */
.role-radio-group {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
justify-content: flex-end;
align-items: flex-start;
padding: 0 0.5rem;
margin-top: -0.25rem;
margin-bottom: 0.25rem;
width: 100%;
}

.role-radio-option {
padding: 0 0.85rem;
position: relative;
display: flex;
align-items: center;
font-size: 1rem;
color: #333333;
}

.role-radio-option input {
margin-right: 0.35rem;
transform: scale(1.15);
transform-origin: center;
}

.role-radio-option img {
width: 18px;
height: 18px;
}

/* Info Icon Styling */
.info-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 1rem;
height: 1rem;
margin-left: 0.5rem;
background-color: #4a90e2;
color: #ffffff;
font-size: 0.75rem;
font-weight: bold;
border-radius: 50%;
cursor: pointer;
position: relative;
transition: background-color 0.2s ease;
z-index: 20;
}

.info-icon:hover {
background-color: #357bd8;
}

.info-icon:hover::after {
content: attr(title);
position: absolute;
top: -1.5rem;
left: auto;
right: 0;
background-color: #333;
color: #fff;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
font-size: 0.75rem;
white-space: normal;
transform: translateX(0);
z-index: 10;
word-wrap: break-word;
}

/* Role Select and Submit Button */
.role-action {
display: flex;
align-items: center;
gap: 8px;
}

.role-select {
padding: 8px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
}

@media (max-width: 768px) {

.add-user-section,
.user-permissions {
width: 100%;
flex-direction: column;
}

.search-filter-section {
flex-wrap: wrap;
}

.filter-select {
width: 100%;
min-width: 0;
flex: 1 1 100%;
}

.role-radio-group {
margin-top: 1rem;
}

.user-input {
margin-bottom: 0;
width: 100%;
}
}

.error-message {
margin-top: 0.5rem;
margin-bottom: 1rem;
}
Loading