Skip to content

Commit 2bbdf01

Browse files
authored
Tracking New TEC Requirements (#845)
### Summary <!-- Required --> This pull requests implements the new TEC requirements in IDOL's submit TEC page. It prevents members from submitting a TEC if they already submitted one in the current 5-week period, unless they missed the last period or they are a lead. ### Notion/Figma Link [https://www.notion.so/Track-new-TEC-requirements-1950ad723ce180e8b18df88a3d7f0388](https://www.notion.so/Track-new-TEC-requirements-1950ad723ce180e8b18df88a3d7f0388) ### Test Plan https://github.com/user-attachments/assets/de0f8025-5b54-4c30-a24b-89dc25313d18
1 parent b1c7af0 commit 2bbdf01

File tree

3 files changed

+106
-11
lines changed

3 files changed

+106
-11
lines changed

frontend/src/components/Forms/TeamEventCreditsForm/TeamEventCreditsForm.tsx

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { TeamEventsAPI } from '../../../API/TeamEventsAPI';
66
import TeamEventCreditDashboard from './TeamEventsCreditDashboard';
77
import styles from './TeamEventCreditsForm.module.css';
88
import ImagesAPI from '../../../API/ImagesAPI';
9-
import { INITIATIVE_EVENTS } from '../../../consts';
9+
import { INITIATIVE_EVENTS, TEC_DEADLINES } from '../../../consts';
1010

1111
const TeamEventCreditForm: React.FC = () => {
1212
// When the user is logged in, `useSelf` always return non-null data.
@@ -31,6 +31,53 @@ const TeamEventCreditForm: React.FC = () => {
3131
});
3232
}, []);
3333

34+
const approvedTECDates = approvedAttendance
35+
.map((attendance) => {
36+
const matchingEvent = teamEventInfoList.find((event) => event.uuid === attendance.eventUuid);
37+
return matchingEvent
38+
? {
39+
date: new Date(matchingEvent.date),
40+
credits: parseFloat(matchingEvent.numCredits)
41+
}
42+
: null;
43+
})
44+
.filter((entry): entry is { date: Date; credits: number } => entry !== null);
45+
46+
const getTECPeriod = (submissionDate: Date) => {
47+
const currentPeriodIndex = TEC_DEADLINES.findIndex((date) => submissionDate <= date);
48+
if (currentPeriodIndex === -1) {
49+
return TEC_DEADLINES.length;
50+
}
51+
return currentPeriodIndex;
52+
};
53+
54+
const tecCounts: number[] = Array.from({ length: TEC_DEADLINES.length }, () => 0);
55+
approvedTECDates.forEach(({ date, credits }) => {
56+
const period = getTECPeriod(date);
57+
if (period < tecCounts.length) tecCounts[period] += credits;
58+
});
59+
60+
const calculateCredits = () => {
61+
const currentPeriod = getTECPeriod(new Date());
62+
const previousPeriod = currentPeriod > 0 ? currentPeriod - 1 : null;
63+
64+
const periodCredits = tecCounts[currentPeriod] || 0;
65+
const previousPeriodCredits = previousPeriod !== null ? tecCounts[currentPeriod - 1] : 1;
66+
67+
if (currentPeriod === 0) {
68+
return periodCredits < 1 ? 1 - periodCredits : 0;
69+
}
70+
if (previousPeriodCredits < 1) {
71+
return periodCredits + previousPeriodCredits < 2
72+
? 2 - previousPeriodCredits - periodCredits
73+
: 0;
74+
}
75+
76+
return periodCredits < 1 ? 1 - periodCredits : 0;
77+
};
78+
79+
const requiredCredits = calculateCredits();
80+
3481
const handleAddIconClick = () => {
3582
setImages((images) => [...images, '']);
3683
};
@@ -142,12 +189,32 @@ const TeamEventCreditForm: React.FC = () => {
142189
<h1>Submit Team Event Credits</h1>
143190
<p>
144191
Earn team event credits for participating in DTI events! Fill out this form every time and
145-
attach a picture of yourself at the event to receive credit.
192+
attach a picture of yourself at the event to receive credit. The current 5-week TEC period
193+
ends on{' '}
194+
{getTECPeriod(new Date()) < TEC_DEADLINES.length
195+
? TEC_DEADLINES[getTECPeriod(new Date())].toDateString()
196+
: 'No upcoming period'}
197+
.
146198
</p>
147199
<div className={styles.inline}>
148200
<label className={styles.bold}>
149201
Select a Team Event: <span className={styles.red_color}>*</span>
150202
</label>
203+
<div className={styles.bold}>
204+
{requiredCredits > 1 && (
205+
<span className={styles.red_color}>
206+
You submitted {2 - requiredCredits} TEC last period so you must submit at least{' '}
207+
{requiredCredits} TEC for this 5-week period.
208+
</span>
209+
)}
210+
</div>
211+
<div className={styles.bold}>
212+
{requiredCredits === 0 && (
213+
<span className={styles.red_color}>
214+
You have already submitted a TEC for this 5-week period.
215+
</span>
216+
)}
217+
</div>
151218
<div className={styles.center_and_flex}>
152219
{teamEventInfoList ? (
153220
<Dropdown
@@ -264,6 +331,8 @@ const TeamEventCreditForm: React.FC = () => {
264331
rejectedAttendance={rejectedAttendance}
265332
isAttendanceLoading={isAttendanceLoading}
266333
setPendingAttendance={setPendingAttendance}
334+
requiredPeriodCredits={requiredCredits}
335+
tecCounts={tecCounts}
267336
/>
268337
</Form>
269338
</div>

frontend/src/components/Forms/TeamEventCreditsForm/TeamEventsCreditDashboard.tsx

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import {
1111
REQUIRED_INITIATIVE_CREDITS,
1212
REQUIRED_LEAD_TEC_CREDITS,
1313
REQUIRED_MEMBER_TEC_CREDITS,
14-
INITIATIVE_EVENTS
14+
INITIATIVE_EVENTS,
15+
MAX_TEC_PER_5_WEEKS,
16+
TEC_DEADLINES
1517
} from '../../../consts';
1618

1719
const TeamEventCreditDashboard = (props: {
@@ -21,14 +23,18 @@ const TeamEventCreditDashboard = (props: {
2123
rejectedAttendance: TeamEventAttendance[];
2224
isAttendanceLoading: boolean;
2325
setPendingAttendance: Dispatch<SetStateAction<TeamEventAttendance[]>>;
26+
requiredPeriodCredits: number;
27+
tecCounts: number[];
2428
}): JSX.Element => {
2529
const {
2630
allTEC,
2731
approvedAttendance,
2832
pendingAttendance,
2933
rejectedAttendance,
3034
isAttendanceLoading,
31-
setPendingAttendance
35+
setPendingAttendance,
36+
requiredPeriodCredits,
37+
tecCounts
3238
} = props;
3339
const [image, setImage] = useState('');
3440
const [open, setOpen] = useState(false);
@@ -104,7 +110,7 @@ const TeamEventCreditDashboard = (props: {
104110
? `, with ${REQUIRED_INITIATIVE_CREDITS} of them being initiative team event credits`
105111
: ''
106112
}
107-
to fulfill this requirement.`;
113+
to fulfill this requirement, completing at least ${MAX_TEC_PER_5_WEEKS} team event credit every 5 weeks.`;
108114
else
109115
headerString = `Since you are a lead, you must complete ${REQUIRED_LEAD_TEC_CREDITS} total team event
110116
credits${
@@ -219,10 +225,15 @@ const TeamEventCreditDashboard = (props: {
219225
) : (
220226
<div>
221227
<div className={styles.inline}>
222-
<label className={styles.bold}>
223-
Your Approved Credits:{' '}
224-
<span className={styles.dark_grey_color}>{approvedCredits}</span>
225-
</label>
228+
<label className={styles.bold}>Approved Credits per Period:</label>
229+
<ul>
230+
{TEC_DEADLINES.map((deadline, index) => (
231+
<li key={index}>
232+
Period {index + 1} (Ends: {deadline.toDateString()}):
233+
<span className={styles.dark_grey_color}> {tecCounts[index]}</span>
234+
</li>
235+
))}
236+
</ul>
226237
</div>
227238

228239
{INITIATIVE_EVENTS && (
@@ -236,11 +247,20 @@ const TeamEventCreditDashboard = (props: {
236247

237248
<div className={styles.inline}>
238249
<label className={styles.bold}>
239-
Remaining Credits Needed:{' '}
240-
<span className={styles.dark_grey_color}>{remainingCredits}</span>
250+
Remaining Credits Needed for Current 5-Week Period:{' '}
251+
<span className={styles.dark_grey_color}>{requiredPeriodCredits}</span>
241252
</label>
242253
</div>
243254

255+
{LEAD_ROLES.includes(userRole) && (
256+
<div className={styles.inline}>
257+
<label className={styles.bold}>
258+
Remaining Total Credits Needed:{' '}
259+
<span className={styles.dark_grey_color}>{remainingCredits}</span>
260+
</label>
261+
</div>
262+
)}
263+
244264
{INITIATIVE_EVENTS && (
245265
<div className={styles.inline}>
246266
<label className={styles.bold}>

frontend/src/consts.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
export const REQUIRED_INITIATIVE_CREDITS = 1;
22
export const REQUIRED_MEMBER_TEC_CREDITS = 3;
33
export const REQUIRED_LEAD_TEC_CREDITS = 6;
4+
export const TEC_DEADLINES = [
5+
new Date('2025-02-23'),
6+
new Date('2025-03-30'),
7+
new Date('2025-05-11')
8+
];
9+
export const MAX_TEC_PER_5_WEEKS = 1;
410
export const ALL_STATUS: Status[] = ['approved', 'pending', 'rejected'];
511
export const INITIATIVE_EVENTS = false;
612
export const ENABLE_COFFEE_CHAT = true;

0 commit comments

Comments
 (0)