### Clone Repository and Install Dependencies (Bash) Source: https://github.com/3raphat/assign-watch/blob/main/README.md This snippet demonstrates how to clone the Assign Watch repository from GitHub and install the necessary project dependencies using pnpm. It requires Git and pnpm to be installed on the system. ```bash git clone https://github.com/thrxpt/assign-watch.git cd assign-watch pnpm install ``` -------------------------------- ### ClassInfo Interface Definition and Example (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt Defines the structure for course information within the LEB2 platform, including the course ID and title. Provides an example object for a specific class. ```typescript interface ClassInfo { id: number; title: string; description: string; } // Example ClassInfo object const exampleClass: ClassInfo = { id: 500, title: "CS101 - Introduction to Programming", description: "Section 1 - Mon/Wed 9:00 AM" }; ``` -------------------------------- ### Activity Interface Definition and Example (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt Defines the structure for an assignment or quiz from the LEB2 platform, including details like title, due date, and submission status. Includes an example object representing data fetched from the LEB2 API. ```typescript interface Activity { id: number; user_id: number; class_id: number; adv_starred: number; group_type: "IND" | "STU"; // Individual or Student group type: "ASM" | "QUZ"; // Assignment or Quiz peer_assessment: number; is_allow_repeat: number; title: string; description: string; start_date: string; due_date: string; edit_group_mode: string; created_at: string; user: number; activity_submission_id: number; class_user_id: number; activity_group_id: null; activity_group_name: null; activity_submission_submitted_at: { date: string; timezone_type: number; timezone: string; }; due_date_exceed: boolean; quiz_submission_is_submitted: number; count_group_member: number; activity_submission_is_late: boolean; fileactivities: number[]; questions: number[]; submissions?: Submission[]; } // Example Activity object from LEB2 API const exampleActivity: Activity = { id: 12345, user_id: 1001, class_id: 500, adv_starred: 0, group_type: "IND", type: "ASM", peer_assessment: 0, is_allow_repeat: 0, title: "Lab Report #3", description: "Submit your completed lab report", start_date: "2024-01-15T00:00:00.000Z", due_date: "2024-01-22T23:59:59.000Z", edit_group_mode: "disabled", created_at: "2024-01-10T08:00:00.000Z", user: 1001, activity_submission_id: 0, class_user_id: 2001, activity_group_id: null, activity_group_name: null, activity_submission_submitted_at: { date: "2024-01-20T14:30:00.000Z", timezone_type: 3, timezone: "Asia/Bangkok" }, due_date_exceed: false, quiz_submission_is_submitted: 0, count_group_member: 1, activity_submission_is_late: false, fileactivities: [101, 102], questions: [] }; ``` -------------------------------- ### Manage Hidden Items with Storage Helper Functions (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt Provides asynchronous helper functions to manage hidden classes and assignments using the WXT storage API. These functions allow for getting, hiding, unhiding, and clearing hidden items, with examples demonstrating their usage. ```typescript // Get all hidden classes async function getHiddenClasses(): Promise { return (await hiddenClassesStorage.getValue()) ?? []; } // Get all hidden assignments async function getHiddenAssignments(): Promise { return (await hiddenAssignmentsStorage.getValue()) ?? []; } // Hide a class async function hideClass(classId: number): Promise { const hidden = await getHiddenClasses(); if (!hidden.includes(classId)) { await hiddenClassesStorage.setValue([...hidden, classId]); } } // Hide an assignment async function hideAssignment(assignmentId: number): Promise { const hidden = await getHiddenAssignments(); if (!hidden.includes(assignmentId)) { await hiddenAssignmentsStorage.setValue([...hidden, assignmentId]); } } // Unhide a class async function unhideClass(classId: number): Promise { const hidden = await getHiddenClasses(); await hiddenClassesStorage.setValue(hidden.filter((id) => id !== classId)); } // Unhide an assignment async function unhideAssignment(assignmentId: number): Promise { const hidden = await getHiddenAssignments(); await hiddenAssignmentsStorage.setValue(hidden.filter((id) => id !== assignmentId)); } // Clear all hidden items async function clearAllHiddenItems(): Promise { await hiddenClassesStorage.setValue([]); await hiddenAssignmentsStorage.setValue([]); } // Usage example - hide and unhide items await hideClass(500); await hideAssignment(12345); const hiddenClasses = await getHiddenClasses(); console.log(`Hidden classes: ${hiddenClasses}`); // Output: Hidden classes: 500 await unhideClass(500); await clearAllHiddenItems(); ``` -------------------------------- ### Get User ID from DOM (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt Retrieves the current user's ID by querying the DOM for an element with the 'data-userid' attribute. This function is useful for identifying the logged-in user within the LEB2 application. It returns the user ID as a string or undefined if not found. ```typescript function getUserId(): string | undefined { const userId = document .querySelector("[data-userid]") ?.getAttribute("data-userid"); return userId; } // Usage const userId = getUserId(); if (userId) { console.log(`Current user ID: ${userId}`); } ``` -------------------------------- ### Build for Production (Bash) Source: https://github.com/3raphat/assign-watch/blob/main/README.md This snippet shows how to build the Assign Watch project for production. It generates optimized code for deployment, with separate commands for Chrome and Firefox builds. ```bash # For Chrome pnpm build # For Firefox pnpm build:firefox ``` -------------------------------- ### Run Development Server (Bash) Source: https://github.com/3raphat/assign-watch/blob/main/README.md These commands are used to run the Assign Watch project in development mode, allowing for live updates and testing. It provides separate commands for Chrome and Firefox development environments. ```bash # For Chrome pnpm dev # For Firefox pnpm dev:firefox ``` -------------------------------- ### WXT Configuration for Browser Extension Source: https://context7.com/3raphat/assign-watch/llms.txt Configuration file for the WXT framework, defining modules, Vite plugins, manifest details, and build hooks. It sets up React support, icon generation, internationalization, and specifies necessary permissions like storage, notifications, and alarms. ```typescript // wxt.config.ts import tailwindcss from "@tailwindcss/vite"; import { defineConfig } from "wxt"; export default defineConfig({ modules: [ "@wxt-dev/module-react", // React support "@wxt-dev/auto-icons", // Auto-generate icon sizes "@wxt-dev/i18n/module", // Internationalization ], vite: () => ({ plugins: [tailwindcss()], }), manifest: { name: "Assign Watch - Extension for LEB2", permissions: [ "storage", // For persisting preferences "notifications", // For deadline alerts "alarms", // For background checking ], default_locale: "en", }, hooks: { "build:manifestGenerated": (wxt, manifest) => { if (wxt.config.mode === "development") { manifest.name += " (DEV)"; } }, }, }); ``` -------------------------------- ### Push Changes to Fork (Bash) Source: https://github.com/3raphat/assign-watch/blob/main/README.md After committing changes, this command pushes the new feature branch to your forked repository on GitHub. This is a necessary step before creating a Pull Request. ```bash git push origin feat/your-amazing-feature ``` -------------------------------- ### Commit Changes with Conventional Commits (Bash) Source: https://github.com/3raphat/assign-watch/blob/main/README.md This snippet illustrates how to stage all changes and commit them using the Conventional Commits format, which is a lightweight convention on top of commit messages. This helps in automating changelog generation and semantic versioning. ```bash git add . git commit -m "feat: add your amazing feature" ``` -------------------------------- ### Create a New Feature Branch (Bash) Source: https://github.com/3raphat/assign-watch/blob/main/README.md This command is part of the contribution workflow, used to create a new Git branch for developing a specific feature. It follows the standard Git branching strategy. ```bash git checkout -b feat/your-amazing-feature ``` -------------------------------- ### Define Storage Items with WXT API (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt Defines various storage items using WXT's storage API for persisting different types of user data and application state. Includes definitions for hidden classes, assignments, filter preferences, sort order, grouping, calendar view, user ID, class info cache, and notification tracking. ```typescript import { storage } from "wxt/utils/storage"; import type { FilterState } from "@/components/assignment-filters"; import type { SortState } from "@/components/assignment-sort"; import type { GroupState } from "@/components/assignment-group"; import type { ClassInfo } from "@/types"; // Hidden classes storage export const hiddenClassesStorage = storage.defineItem( "local:hiddenClasses", { fallback: [] } ); // Hidden assignments storage export const hiddenAssignmentsStorage = storage.defineItem( "local:hiddenAssignments", { fallback: [] } ); // Filter preferences storage export const filtersStorage = storage.defineItem( "local:assignmentFilters", { fallback: { submissionStatus: { submitted: true, notSubmitted: true }, assignmentType: { assignment: true, quiz: true }, groupType: { individual: true, group: true }, }, } ); // Sort preferences storage export const sortStorage = storage.defineItem( "local:assignmentSort", { fallback: { sortBy: "dueDate", direction: "asc" } } ); // Grouping preferences storage export const groupStorage = storage.defineItem( "local:assignmentGroup", { fallback: { groupBy: "class" } } ); // Calendar view mode storage export type ShowCalendarBy = "month" | "week"; export const showCalendarByStorage = storage.defineItem( "local:showCalendarBy", { fallback: "month" } ); // User ID storage for background service worker export const userIdStorage = storage.defineItem( "local:userId", { fallback: null } ); // Class info cache for background notifications export const classInfoStorage = storage.defineItem( "local:classInfo", { fallback: [] } ); // Notification tracking (24h before deadline) export const notifiedAssignmentsStorage = storage.defineItem( "local:notifiedAssignments", { fallback: [] } ); // Notification tracking (1h before deadline) export const notifiedAssignments1hStorage = storage.defineItem( "local:notifiedAssignments1h", { fallback: [] } ); ``` -------------------------------- ### Locale-Aware Date Formatting (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt A utility function `formatDate` that formats a `Date` object into a string based on a provided format pattern. It uses the `date-fns` library and supports locale-specific formatting (English and Thai) determined by an internationalization configuration. This function is useful for displaying dates in a user-friendly and localized manner. ```typescript import { format } from "date-fns"; import { enUS, th } from "date-fns/locale"; import { i18n } from "#i18n"; function formatDate(date: Date, formatStr: string): string { return format(date, formatStr, { locale: i18n.t("@@ui_locale") === "th" ? th : enUS, }); } // Usage examples const date = new Date("2024-01-22T14:30:00Z"); formatDate(date, "p"); // Returns: "2:30 PM" formatDate(date, "eeee, d MMM yyyy"); // Returns: "Monday, 22 Jan 2024" formatDate(date, "MMMM yyyy"); // Returns: "January 2024" formatDate(date, "EEE"); // Returns: "Mon" ``` -------------------------------- ### Background Script for Assignment Notifications (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt This TypeScript background script monitors assignments and sends notifications before deadlines. It uses browser alarms to periodically check for upcoming assignments and browser notifications to alert the user. It also handles clicks on notification buttons to open relevant assignment pages. ```typescript import { browser } from "wxt/browser"; import { defineBackground } from "wxt/utils/define-background"; import { classInfoStorage, getAssignments, getSubmissionStatus, notifiedAssignments1hStorage, notifiedAssignmentsStorage, userIdStorage, } from "@/lib/utils"; export default defineBackground(() => { // Show onboarding page on install browser.runtime.onInstalled.addListener((details) => { if (details.reason === "install") { browser.tabs.create({ url: browser.runtime.getURL("/onboarding.html"), }); } }); // Create alarm to check assignments every minute browser.alarms.create("checkAssignments", { periodInMinutes: 1 }); // Handle alarm - check for upcoming deadlines browser.alarms.onAlarm.addListener(async (alarm) => { if (alarm.name === "checkAssignments") { const userId = await userIdStorage.getValue(); const classInfo = await classInfoStorage.getValue(); const notifiedAssignments = (await notifiedAssignmentsStorage.getValue()) ?? []; const notifiedAssignments1h = (await notifiedAssignments1hStorage.getValue()) ?? []; if (!(userId && classInfo)) return; const now = new Date(); const tomorrow = new Date(now.getTime() + 24 * 60 * 60 * 1000); const oneHour = new Date(now.getTime() + 60 * 60 * 1000); for (const cls of classInfo) { const assignments = await getAssignments(cls.id, userId); for (const assignment of assignments) { const isSubmitted = getSubmissionStatus(assignment) === "submitted" || getSubmissionStatus(assignment) === "submitted_late"; const dueDate = new Date(assignment.due_date); const isOverdue = dueDate < now; // 24-hour notification if ( !notifiedAssignments.includes(assignment.id) && !isSubmitted && dueDate > now && dueDate <= tomorrow ) { browser.notifications.create( `assignwatch-${assignment.type}-${assignment.class_id}-${assignment.id}`, { type: "basic", iconUrl: browser.runtime.getURL("/icons/128.png"), title: "Assignment Due Soon!", message: `"${assignment.title}" is due in less than 24 hours.`, buttons: [{ title: "View Assignment" }], } ); notifiedAssignments.push(assignment.id); } // 1-hour notification if ( !notifiedAssignments1h.includes(assignment.id) && !isSubmitted && dueDate > now && dueDate <= oneHour ) { browser.notifications.create( `assignwatch-${assignment.type}-${assignment.class_id}-${assignment.id}-1h`, { type: "basic", iconUrl: browser.runtime.getURL("/icons/128.png"), title: "Assignment Due Soon!", message: `"${assignment.title}" is due in less than 1 hour.`, buttons: [{ title: "View Assignment" }], } ); notifiedAssignments1h.push(assignment.id); } } } await notifiedAssignmentsStorage.setValue(notifiedAssignments); await notifiedAssignments1hStorage.setValue(notifiedAssignments1h); } }); // Handle notification button clicks browser.notifications.onButtonClicked.addListener((notificationId) => { if (notificationId.startsWith("assignwatch-")) { const [type, classId, assignmentId] = notificationId.split("-").slice(1); browser.tabs.create({ url: `https://app.leb2.org/class/${classId}/${type === "ASM" ? "activity" : "quiz"}/${assignmentId}`, }); } }); }); ``` -------------------------------- ### React Hook for Watching Storage Changes (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt A custom React hook `useHiddenItems` that utilizes `useEffect` to load and watch for changes in browser storage for hidden classes and assignments. It returns the current state of these arrays and cleans up watchers on unmount. Dependencies include React hooks and utility functions for storage access. ```typescript import { useEffect, useState } from "react"; import { hiddenClassesStorage, hiddenAssignmentsStorage } from "@/lib/utils"; function useHiddenItems() { const [hiddenClasses, setHiddenClasses] = useState([]); const [hiddenAssignments, setHiddenAssignments] = useState([]); useEffect(() => { // Load initial values const loadStorageData = async () => { const [classes, assignments] = await Promise.all([ hiddenClassesStorage.getValue(), hiddenAssignmentsStorage.getValue(), ]); setHiddenClasses(classes ?? []); setHiddenAssignments(assignments ?? []); }; loadStorageData(); // Watch for changes const unwatchClasses = hiddenClassesStorage.watch( (newValue: number[] | undefined) => { setHiddenClasses(newValue ?? []); } ); const unwatchAssignments = hiddenAssignmentsStorage.watch( (newValue: number[] | undefined) => { setHiddenAssignments(newValue ?? []); } ); return () => { unwatchClasses(); unwatchAssignments(); }; }, []); return { hiddenClasses, hiddenAssignments }; } ``` -------------------------------- ### Fetch Assignments from LEB2 API (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt Fetches all assignments for a specific class from the LEB2 API. It filters out assignments without due dates and requires a class ID. Optionally, a user ID can be provided. The function returns an array of `Activity` objects. ```typescript import type { Activity, RootResponse } from "@/types"; async function getAssignments(classId: number, userId?: string): Promise { const finalUserId = userId ?? getUserId(); const res = await fetch( `https://app.leb2.org/api/get/assessment-activities/student?class_id=${classId}&student_id=${finalUserId}&filter_groups[0][filters][0][key]=class_id&filter_groups[0][filters][0][value]=${classId}&sort[]=sequence&sort[]=id&select[]=activities:id,user_id,class_id,adv_starred,group_type,type,peer_assessment,is_allow_repeat,title,description,start_date,due_date,edit_group_mode,created_at&select[]=user:id,firstname_en,lastname_en,firstname_th,lastname_th&includes[]=user:sideload&includes[]=fileactivities:ids&includes[]=questions:ids` ); const data = (await res.json()) as RootResponse; return data.activities.filter((activity) => activity.due_date !== null); } // Usage example - fetch assignments for a class const classId = 500; const assignments = await getAssignments(classId); console.log(`Found ${assignments.length} assignments for class ${classId}`); // With explicit userId const assignmentsForUser = await getAssignments(500, "1001"); ``` -------------------------------- ### CalendarView Component for Assignments Source: https://context7.com/3raphat/assign-watch/llms.txt An interactive React component to display assignments in a calendar format. It supports weekly and monthly views, navigation, and visual cues for assignment status. It takes assignment data, class information, and filtering functions as props. ```tsx import { CalendarView } from "@/components/calendar-view"; import type { Activity, ClassInfo } from "@/types"; interface CalendarViewProps { allClassInfo: ClassInfo[]; allAssignments: (Activity[] | undefined)[]; hiddenAssignments: number[]; applyFilters: (assignment: Activity) => boolean; } // Usage // Features: // - Toggle between week and month views // - Navigate to previous/next week or month // - Click to return to current week/month // - Color-coded assignments by submission status // - Context menu to hide assignments // - Popover for days with many assignments ``` -------------------------------- ### Assignment Component for Displaying Assignment Details (React/TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt This React component, written in TypeScript, displays a single assignment's details. It shows the assignment title, due date, submission status, type, and group type. It also includes a context menu with an option to hide the assignment. The component is designed to be used within a list view of assignments. ```tsx import { Assignment } from "@/components/assignment"; import type { Activity, ClassInfo } from "@/types"; // Props interface interface AssignmentProps { assignment: Activity; classInfo?: ClassInfo; // Optional - shown when grouped by due date } // Usage in list view // The component renders: // - Assignment title as clickable link // - Due date and time // - Submission status badge (green/red/amber) // - Type badge (Assignment/Quiz) // - Group type badge (Individual/Group) // - Context menu with "Hide Assignment" option ``` -------------------------------- ### Extract Class Info from DOM (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt Parses class cards and associated text elements from the LEB2 page's DOM to extract class information. It identifies class cards by the '.class-card' selector and text content using '#font-color-main-card p'. Archived classes with a settings icon are skipped. Returns an array of `ClassInfo` objects. ```typescript function getAllClassInfo(): ClassInfo[] { const classCards = document.querySelectorAll(".class-card"); const classTextElements = document.querySelectorAll("#font-color-main-card p"); const classesInfo: ClassInfo[] = []; for (let i = 0; i < classCards.length; i++) { const cardName = classCards[i].getAttribute("name"); const classId = cardName?.split("-")[1]; if (!classId) continue; const cardElement = classCards[i]; const nextElement = cardElement.nextElementSibling; // Skip classes with settings icon (likely archived) if (nextElement?.tagName === "UL") { const settingsIcon = nextElement.querySelector( "li > div > div.icon-setting-2.fix-oncard-btn" ); if (settingsIcon) continue; } const classTitle = classTextElements[i * 2].textContent; const classDescription = classTextElements[i * 2 + 1].textContent; classesInfo.push({ id: Number(classId), title: classTitle, description: classDescription, }); } return classesInfo; } // Usage - extract all enrolled classes from the page const allClasses = getAllClassInfo(); console.log(`Found ${allClasses.length} classes`); // Output: Found 5 classes ``` -------------------------------- ### HiddenItemsManager Component for Restoration Source: https://context7.com/3raphat/assign-watch/llms.txt A React component that displays and allows restoration of hidden classes and assignments. It shows counts of hidden items, lists them, and provides options to unhide individual items or clear all hidden items. It also displays tips when no items are hidden. ```tsx import { HiddenItemsManager } from "@/components/hidden-items-manager"; import type { Activity, ClassInfo } from "@/types"; interface HiddenItemsManagerProps { hiddenClasses: number[]; hiddenAssignments: number[]; allClassInfo: ClassInfo[]; allAssignments: (Activity[] | undefined)[]; } // Usage // Features: // - Shows count of hidden items // - Lists hidden classes and assignments // - Click to unhide individual items // - "Clear All" button to restore everything // - Shows tips when nothing is hidden ``` -------------------------------- ### Relative Date Formatting with Status Indicator (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt A utility function `formatDateRelative` that formats a given `Date` object into a human-readable relative time string (e.g., '2 days ago', 'in 3 hours') using the `moment.js` library. It also determines a status ('late', 'today', 'upcoming') based on the date's relation to the current time. It supports locale switching based on an internationalization configuration. ```typescript import moment from "moment/min/moment-with-locales"; import { i18n } from "#i18n"; type DateStatus = "late" | "today" | "upcoming"; function formatDateRelative(date: Date): { text: string; status: DateStatus } { moment.locale(i18n.t("@@ui_locale") === "th" ? "th" : "en"); return { text: moment(date).fromNow(), status: moment(date).isBefore(moment()) ? "late" : moment(date).isSame(new Date(), "day") ? "today" : "upcoming", }; } // Usage examples const futureDate = new Date(Date.now() + 2 * 24 * 60 * 60 * 1000); const result1 = formatDateRelative(futureDate); // Returns: { text: "in 2 days", status: "upcoming" } const today = new Date(); const result2 = formatDateRelative(today); // Returns: { text: "a few seconds ago", status: "today" } const pastDate = new Date(Date.now() - 3 * 24 * 60 * 60 * 1000); const result3 = formatDateRelative(pastDate); // Returns: { text: "3 days ago", status: "late" } ``` -------------------------------- ### FilterState Interface Definition and Default (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt Defines the structure for managing filtering options in the Assign Watch UI, covering submission status, assignment type, and group type. Includes the default filter state. ```typescript interface FilterState { submissionStatus: { submitted: boolean; notSubmitted: boolean; }; assignmentType: { assignment: boolean; quiz: boolean; }; groupType: { individual: boolean; group: boolean; }; } // Default filter state const defaultFilters: FilterState = { submissionStatus: { submitted: true, notSubmitted: true, }, assignmentType: { assignment: true, quiz: true, }, groupType: { individual: true, group: true, }, }; ``` -------------------------------- ### AssignmentFilters Component for Filtering Source: https://context7.com/3raphat/assign-watch/llms.txt A React component providing a dropdown menu for filtering assignments. It manages filter states for submission status, assignment type, and group type, and allows updates via a callback function. User preferences are persisted using storage. ```tsx import { AssignmentFilters, FilterState } from "@/components/assignment-filters"; interface AssignmentFiltersProps { filters: FilterState; onFiltersChange: (filters: FilterState) => void; } // Usage const [filters, setFilters] = useState({ submissionStatus: { submitted: true, notSubmitted: true }, assignmentType: { assignment: true, quiz: true }, groupType: { individual: true, group: true }, }); const handleFiltersChange = async (newFilters: FilterState) => { setFilters(newFilters); await filtersStorage.setValue(newFilters); }; // Shows filter count badge when filters are active // Prevents unchecking all options in a category ``` -------------------------------- ### Determine Assignment Submission Status (TypeScript) Source: https://context7.com/3raphat/assign-watch/llms.txt Determines the submission status of an assignment based on its properties, such as `activity_submission_id`, `activity_submission_is_late`, `quiz_submission_is_submitted`, and `due_date_exceed`. It returns one of the predefined `SubmissionStatus` enum values. ```typescript type SubmissionStatus = | "submitted" | "submitted_late" | "not_submitted" | "in_progress" | "quiz_not_submitted"; function getSubmissionStatus(assignment: Activity): SubmissionStatus { if (assignment.activity_submission_id) { if (assignment.activity_submission_is_late) { return "submitted_late"; } if (assignment.quiz_submission_is_submitted === 0) { return "quiz_not_submitted"; } return "submitted"; } if (assignment.due_date_exceed) { return "not_submitted"; } return "in_progress"; } // Usage examples const status1 = getSubmissionStatus({ ...exampleActivity, activity_submission_id: 123, activity_submission_is_late: false }); // Returns: "submitted" const status2 = getSubmissionStatus({ ...exampleActivity, activity_submission_id: 0, due_date_exceed: true }); // Returns: "not_submitted" const status3 = getSubmissionStatus({ ...exampleActivity, activity_submission_id: 0, due_date_exceed: false }); // Returns: "in_progress" ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.