diff --git a/RIT-EMS-main/EMS_DOCUMENTATION.md b/RIT-EMS-main/EMS_DOCUMENTATION.md deleted file mode 100644 index 11c7fff..0000000 --- a/RIT-EMS-main/EMS_DOCUMENTATION.md +++ /dev/null @@ -1,407 +0,0 @@ -# RIT Event Management System (EMS) - Comprehensive System Documentation - -The **RIT Event Management System (EMS)** is a state-of-the-art web application developed for the Rajalakshmi Institute of Technology (RIT) to handle, automate, audit, and coordinate campus-wide events, venue requests, and academic schedules. - ---- - -## 1. Executive Summary & Core Objective - -In an active educational institution like RIT (and the sister school RSB), coordinating events such as academic workshops, guest lectures, sports events, student club activities, and high-priority placement drives presents significant scheduling challenges: -1. **Venue Booking Conflicts:** Overlapping bookings for major facilities (e.g., auditoriums, seminar halls, labs). -2. **Complex Approvals:** Manual routing of proposals from Faculty, through Heads of Departments (HOD), up to the Principal. -3. **Academic Semester Swapping:** Transitioning routine weekly/monthly schedules from one semester to the next. -4. **Data Overload:** Migrating bulk event schedules from legacy tools or Google Forms. - -The EMS platform addresses these challenges by offering: -* **Interactive Venues at a Glance:** Live timeline visuals showing hourly and daily room utilization. -* **Role-Based Workflows:** Direct automated routing of event proposals based on standard institutional roles. -* **Smart Conflict Solver:** Automated, real-time database queries matching proposed locations, dates, and institutions. -* **Overriding Placement System:** Privileged scheduling options for Placement staff to secure facilities. -* **Semester Swap Simulation:** Dynamic tool mapping active calendars onto subsequent semesters with calendar shift simulations. -* **Fuzzy Excel Parser:** In-browser sheet processor mapping arbitrary data columns into structured event templates. - ---- - -## 2. System Architecture & Tech Stack - -The platform runs on a serverless, database-first architecture using Firebase. All backend endpoints are intercepted and resolved client-side in the browser. - -```mermaid -graph LR - subgraph Frontend [React SPA Client] - React[React 19 / TS / Vite] - Router[Component & Context Routing] - Tailwind[Tailwind CSS & Glassmorphism UI] - Framer[Framer Motion Animations] - Interceptor[Fetch Interceptor firebaseBackend.ts] - end - - subgraph Backend [Firebase Cloud Platform] - Firestore[(Cloud Firestore Database)] - Auth[Firebase Authentication] - end - - React <--> Interceptor - Interceptor <-->|Firebase Client SDK| Firestore - Interceptor <-->|Firebase Client SDK| Auth -``` - -### Firebase Backend Specifications -* **Database Service:** Cloud Firestore for real-time document storage. -* **Data Access & Interception:** A client-side fetch interceptor implemented in `firebaseBackend.ts` intercepts all `/api/*` REST HTTP requests and handles the queries/transactions natively using the Firebase Client SDK. -* **Authentication:** Google OAuth 2.0 and email/passcode flows, integrated with Firebase Auth and sync'd to the `ems_users` Firestore collection. -* **Security & Roles:** Verified inside frontend routing handlers and secured using Firestore Security Rules. - -### Frontend Specifications -* **Core Framework:** React 19, TypeScript, Vite -* **State Management:** React Context API (specifically `AuthContext` managing authenticated states). -* **Styling System:** Tailwind CSS with custom global CSS utilities for modern glassmorphism design layouts. -* **Animations:** Framer Motion powering tab transitions, modal slides, and responsive components. -* **Icon Suite:** Lucide React -* **Utility Libraries:** - * `date-fns`: Date formatting, calendar scheduling, and duration differences. - * `xlsx`: In-browser parsing of spreadsheet files (.xlsx, .csv). - ---- - -## 3. Database Schema & Architecture - -The database contains four primary collections managed in Cloud Firestore. - -```mermaid -erDiagram - USERS { - Long id PK - String email UK - String password - String fullName - String role - String department - Boolean isClubCoordinator - Boolean isPlacementStaff - Boolean isClassIncharge - Integer classStrength - String inchargeClass - String inchargeBatch - String inchargeSection - } - EVENTS { - Long id PK - String title - Text description - LocalDateTime startDate - LocalDateTime endDate - String location - String category - String type - String institution - String department - String status - String guestName - String guestSocialProfile - Double budget - Boolean hasRegistrationFee - Double registrationFee - Text rejectionReason - String groupRequestId - Long proposer_id FK - } - CLASS_MAPPING { - Long id PK - String institution - String department - String academicYear - String status - } - INSTITUTIONAL_NOTE { - Long id PK - String content - LocalDate targetDate - String authorName - String authorEmail - LocalDateTime createdAt - } - USERS ||--o{ EVENTS : proposes -``` - -### A. User Entity (`users`) -Holds profiles, credentials, permissions, and roles. -* `id` (Long, Primary Key): Auto-incremented. -* `email` (String, Unique): Institutional email (`@rit.edu` or `@ritindia.edu`). -* `password` (String): BCrypt hashed password representation. -* `fullName` (String): User's display name. -* `role` (String): Enum-like values: `ADMIN`, `PRINCIPAL`, `HOD`, `FACULTY`, `PLACEMENT`. -* `department` (String): Department names (e.g., `CSE`, `AI&ML`, `ECE`, `H&S Dept`, etc.). -* `isClubCoordinator` (Boolean): Authorizes coordination of student club events. -* `isPlacementStaff` (Boolean): Grants authority to override schedule conflicts for placement events. -* `isClassIncharge` (Boolean): Authorizes dashboard widgets showing class sizes and updates. -* `classStrength` (Integer): Student count for the in-charge class. -* `inchargeClass` / `inchargeBatch` / `inchargeSection` (String): Specific details identifying the class in charge. -* `assignedClubs` (ElementCollection): List of student clubs managed by the user. - -### B. Event Entity (`events`) -Details individual event proposals, resources, status, and audit workflows. -* `id` (Long, Primary Key): Auto-incremented. -* `title` (String, Not Null): The name of the event. -* `description` (Text): Detailed agenda or description. -* `startDate` / `endDate` (LocalDateTime): Timestamps for the event duration. -* `location` (String): Specific venue (e.g., `GB 4th floor auditorium`, `Wozniak Auditorium`, `Mini Seminar Hall`). -* `category` (String): Dictates the routing logic: `ACADEMIC`, `CLUB`, `PLACEMENT`, `SPORTS`, `INSTITUTIONAL`. -* `type` (String): Event type (e.g., `Workshop`, `Seminar`, `Guest Lecture`, `Competition`). -* `institution` (String): Targets `RIT` or `RSB`. -* `department` (String): Proposing department. -* `academicYears` (ElementCollection): Targeted cohorts (e.g., `1st Year`, `2nd Year`, `3rd Year`, `4th Year`). -* `targetedSections` (ElementCollection): Target sections (e.g., `A`, `B`, `C`). -* `status` (String): Current lifecycle stage: - * `REQUESTED`: Submitted by Faculty, pending HOD approval. - * `PENDING_PR`: Approved by HOD, pending Principal approval (or submitted directly by HOD/Placement, bypassing HOD stage). - * `APPROVED`: Fully approved, venue locked, and calendar entry created. - * `COMPLETED`: Event time has elapsed. - * `CANCELLED`: Cancelled manually or displaced by an overriding placement event. - * `HOD_REJECTED`: Rejected at the HOD stage. - * `PRINCIPAL_REJECTED`: Rejected at the Principal stage. -* `guestName` / `guestSocialProfile` (String): Guest details and links. -* `requirements` (ElementCollection): Resources required (e.g., `Mementos`, `Projector`, `Lunch`, `Wi-Fi`, `Mic`). -* `budget` (Double): Requested budget. -* `hasRegistrationFee` (Boolean) / `registrationFee` (Double): Entry fee details. -* `sponsors` (ElementCollection): Partner/sponsor list. -* `proposer` (ManyToOne -> User): Reference to user who created the event proposal. -* `rejectionReason` (Text): Comments input by HOD or Principal when rejecting. -* `groupRequestId` (String): Link identifier for recurring events. - -### C. ClassMapping Entity (`classes`) -Used for maintaining lists of student cohorts and sections. -* `id` (Long, Primary Key) -* `institution` (String): `RIT` or `RSB`. -* `department` (String): Department name. -* `academicYear` (String): `1st Year`, `2nd Year`, etc. -* `sections` (ElementCollection): List of associated sections. -* `status` (String): Defaults to `Ready`. - -### D. InstitutionalNote Entity (`institutional_notes`) -Pinned warnings, announcements, or notifications on the main calendar. -* `id` (Long, Primary Key) -* `content` (String, Not Null) -* `targetDate` (LocalDate): Date on which the note should appear on the calendar. -* `authorName` / `authorEmail` (String): Creator info. -* `createdAt` (LocalDateTime) - ---- - -## 4. Role-Based Access Control & Navigation - -The frontend app adjusts its views, menus, and dashboard components dynamically based on the logged-in user's role and authorization flags: - -| Role / Flag | Menu Items Available | Special Features | -| :--- | :--- | :--- | -| **FACULTY** | Dashboard, Propose Event, All Events, Institutional Checklist, Event History | Can see personal proposal status, updates class strength if marked as Class Incharge. | -| **HOD** | Dashboard, Propose Event, Approvals, All Events, Institutional Checklist, Event History, Automation Console | Can approve/reject department proposals. Can access the Semester Swap simulator. | -| **PRINCIPAL** | Dashboard, Propose Event, Approvals, All Events, Institutional Checklist, Event History, Automation Console | Can approve/reject any pending events. Master checklist dashboard widget access. | -| **PLACEMENT** | Dashboard, Propose Event, All Events, Institutional Checklist, Event History | Proposes placement events that can optionally override existing bookings. | -| **ADMIN** | Dashboard, Propose Event, Approvals, Clubs Checklist, All Events, Institutional Checklist, Event History, Automation Console, Excel Import, Class Configurations, User Management | Full control over users, classes, excel file parses, database configurations, and approvals. | -| **isClubCoordinator = true** | Add *Clubs* Menu option | Grants access to the Club Checklist page to coordinate student club activities. | - ---- - -## 5. Site Map & Route Specification - -The system uses a Single-Page Application (SPA) shell in [App.tsx](file:///e:/RIT-EMS-main/frontend/src/App.tsx) driven by state routing. - -```mermaid -graph TD - Login[LoginPage.tsx] -->|POST /api/auth/login success| Shell[App.tsx SPA Shell] - - subgraph SPA Navigation & Components - Shell -->|dashboard| Overview[Overview.tsx] - Shell -->|propose| Proposal[EventProposalForm.tsx] - Shell -->|approvals| Approvals[ApprovalsView.tsx] - Shell -->|clubs| Clubs[ClubInstitutionalChecklist.tsx] - Shell -->|events| Events[AllEvents.tsx] - Shell -->|checklist| Checklist[InstitutionalChecklist.tsx] - Shell -->|history| History[EventHistory.tsx] - Shell -->|classes| ClassMgmt[ClassManagement.tsx] - Shell -->|automation| Automation[AutomationView.tsx] - Shell -->|import-excel| ExcelImport[ExcelImport.tsx] - Shell -->|user-management| UserMgmt[UserManagement.tsx] - end - - subgraph Embedded Widgets in Overview - Overview --> Cal[InstitutionalCalendar.tsx] - Overview --> Ven[VenuesAtGlance.tsx] - Overview --> Time[VenueTimeline.tsx] - Overview --> Fac[FacultyEventManagement.tsx] - Overview --> Pri[PrincipalMasterChecklist.tsx] - end -``` - -### Route & Component Specification Details - -#### 1. Login Gate -* **Component:** [LoginPage.tsx](file:///e:/RIT-EMS-main/frontend/src/pages/LoginPage.tsx) -* **Access:** Anonymous/Public. -* **Description:** Provides a modern UI with split-card layout, college logos, and forms for institutional email & password. -* **API Endpoint called:** `POST /api/auth/login` - -#### 2. Overview Dashboard (`dashboard`) -* **Component:** [Overview.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/Overview.tsx) -* **Access:** All Authenticated Users. -* **Features:** - * Displays circular progress indicators representing events by category. - * Shows role-specific cards (e.g., Faculty see their proposals; Class Incharges see class stats; Principals see Master Checklist). -* **Embedded Sub-Components:** - * **[InstitutionalCalendar.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/InstitutionalCalendar.tsx):** Interactive calendar with day-based event popovers and notes. - * **[VenuesAtGlance.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/VenuesAtGlance.tsx):** Displays a grid of main campus venues and their immediate status. - * **[VenueTimeline.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/VenueTimeline.tsx):** A timeline mapping hour blocks for venue bookings. - * **[FacultyEventManagement.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/FacultyEventManagement.tsx):** Faculty-specific event table displaying submission stages. - * **[PrincipalMasterChecklist.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/PrincipalMasterChecklist.tsx):** Principal-specific checklist audit view. -* **API Endpoints called:** `GET /api/events`, `GET /api/notes`, `POST /api/notes`, `PUT /api/admin/users/{id}` (for class updates). - -#### 3. Propose Event (`propose`) -* **Component:** [EventProposalForm.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/EventProposalForm.tsx) -* **Access:** All Authenticated Users. -* **Features:** - * Handles standard scheduling, multi-select sections/target academic years, and venue requirements (Catering, Projector, Wi-Fi, etc.). - * Support for recurring group bookings. - * Placement role can toggle "Override Conflicts". -* **API Endpoints called:** `POST /api/events/propose`, `PUT /api/events/{id}` - -#### 4. Approvals (`approvals`) -* **Component:** [ApprovalsView.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/ApprovalsView.tsx) -* **Access:** HOD and PRINCIPAL. -* **Features:** Tabulated view listing pending events. HOD reviews `REQUESTED` events. Principal reviews `PENDING_PR` events. Rejections trigger a popover modal requesting comment. -* **API Endpoints called:** `GET /api/events`, `POST /api/events/{id}/approve`, `POST /api/events/{id}/reject` - -#### 5. Clubs Checklist (`clubs`) -* **Component:** [ClubInstitutionalChecklist.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/ClubInstitutionalChecklist.tsx) -* **Access:** Club Coordinators and Admin. -* **Features:** Filters events specifically marked under the `CLUB` category and presents a checklist layout. -* **API Endpoints called:** `GET /api/events` - -#### 6. All Events (`events`) -* **Component:** [AllEvents.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/AllEvents.tsx) -* **Access:** All Authenticated Users. -* **Features:** Grid searching, text filters, date search, category chips, and delete/edit buttons for event owners or Admin. -* **API Endpoints called:** `GET /api/events`, `DELETE /api/events/{id}` - -#### 7. Institutional Checklist (`checklist`) -* **Component:** [InstitutionalChecklist.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/InstitutionalChecklist.tsx) -* **Access:** All Authenticated Users. -* **Features:** Visual grid displaying requirements (Wi-Fi, catering, projector) for approved upcoming events, highlighting completeness. -* **API Endpoints called:** `GET /api/events` - -#### 8. Event History (`history`) -* **Component:** [EventHistory.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/EventHistory.tsx) -* **Access:** All Authenticated Users. -* **Features:** Lists elapsed events with filters. Features summary stats showing total budget spent and event count. -* **API Endpoints called:** `GET /api/events` - -#### 9. Automation Console (`automation`) -* **Component:** [AutomationView.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/AutomationView.tsx) -* **Access:** HOD, PRINCIPAL, and ADMIN. -* **Features:** - * **Semester Swap:** Selects a batch of events (e.g., CSE 3rd Year RIT) and maps them to a future date range (+/- 6 months) to replicate schedules. - * **Conflict Analysis:** In-memory check identifying overlap with existing entries or weekends, recommending alternatives. - * **Review Gate:** Verification modal showing proposed events before batch creation. -* **API Endpoints called:** `GET /api/events`, `POST /api/events/batch-create` - -#### 10. Excel Import (`import-excel`) -* **Component:** [ExcelImport.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/ExcelImport.tsx) -* **Access:** ADMIN. -* **Features:** - * File uploader utilizing `xlsx` to parse spreadsheet columns. - * Mapping panel to align sheet columns with event details. - * Proposer verification: Automatically registers unrecognized emails (`password` defaults to `Password@123`). - * Conflict resolver indicating venue/time overlaps and recommending shifts. -* **API Endpoints called:** `GET /api/events`, `GET /api/admin/users`, `POST /api/admin/users`, `POST /api/events/batch-create` - -#### 11. Class Configurations (`classes`) -* **Component:** [ClassManagement.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/ClassManagement.tsx) -* **Access:** ADMIN. -* **Features:** Add classes, update sections, and perform the "Yearly Promotion" (e.g. promoting 1st Years -> 2nd Years, deleting graduating 4th Years). -* **API Endpoints called:** `GET /api/classes`, `POST /api/classes`, `DELETE /api/classes/{id}`, `POST /api/classes/promote` - -#### 12. User Management (`user-management`) -* **Component:** [UserManagement.tsx](file:///e:/RIT-EMS-main/frontend/src/components/dashboard/UserManagement.tsx) -* **Access:** ADMIN. -* **Features:** CRUD management for user accounts. Controls department assignments, club responsibilities, role changes, and passwords. -* **API Endpoints called:** `GET /api/admin/users`, `POST /api/admin/users`, `PUT /api/admin/users/{id}`, `DELETE /api/admin/users/{id}` - ---- - -## 6. Key Workflows & Logic Specs - -### A. Real-time Conflict Auditing Engine -During event creation, the application validates for timing and location conflicts directly against Firestore. -1. The frontend query helper scan the `ems_events` collection to identify overlapping bookings: - $$\text{Start}_A < \text{End}_B \quad \text{and} \quad \text{End}_A > \text{Start}_B$$ -2. **Placement Override Case:** - If the proposer is a `PLACEMENT` coordinator and `cancelConflicting=true` is checked: - * The fetch interceptor updates all conflicting Firestore event documents' status to `CANCELLED`. - * It registers a rejection/displacement reason on the cancelled events. - * The placement event is saved in `PENDING_PR` (for Principal review). -3. **General Case:** - If conflicts exist and it is not an overridden placement, a conflict message is returned and flagged to the user. - -### B. Event Approval Pipeline -The approval flow routes events dynamically depending on the proposer: -``` - [ Faculty Proposes Event ] - │ - ▼ - [ HOD Desk Review ] - (Status: REQUESTED) - / \ - Approve Reject ──► [ Status: HOD_REJECTED ] - / - ▼ - [ Principal Desk Review ] - (Status: PENDING_PR) - / \ - Approve Reject ──► [ Status: PRINCIPAL_REJECTED ] - / - ▼ -[ Status: APPROVED ] -(Venue Locked / Calendar Pinned) -``` -* **Bypass Rule 1:** If the proposer is the **Principal**, the event is auto-approved (`APPROVED`). -* **Bypass Rule 2:** If the proposer is an **HOD**, or the event category is **Club**, **Placement**, or **Institutional**, the proposal bypasses HOD review and goes directly to the Principal (`PENDING_PR`). - -### C. Semester Swap Calendar Shift -This tool allows admins/HODs/Principals to duplicate schedules for new semesters: -1. Select source filters (e.g., Department = CSE, Academic Year = 3rd Year). -2. The UI fetches matching events, maps them to target dates (shifted by a user-specified offset, e.g., 180 days), and simulates their placement. -3. The UI checks each shifted event against the database for venue conflicts or weekends: - * If an event lands on a Saturday or Sunday, the UI suggests shifting it to the nearest Friday or Monday. - * If a venue conflict occurs, the UI flags it and suggests venue changes. -4. Clicking "Commit" submits a bulk payload to `POST /api/events/batch-create`. - ---- - -## 7. Developer & Local Deployment Guide - -### Prerequisites -* Node.js (v18+) - -### 1. Launch Frontend Client -1. Navigate to the `frontend` folder. -2. Install dependencies: - ```bash - npm install - ``` -3. Run the development server: - ```bash - npm run dev - ``` -4. The frontend runs at `http://localhost:5173`. - -### 2. Firebase Configurations -* The Firebase client config is hardcoded in `frontend/src/lib/firebaseBackend.ts` to connect directly to the Firestore backend. -* On first load, if the database collections (`ems_users` or `ems_classes`) are empty, `firebaseBackend.ts` automatically seeds default institutional accounts and mock classes. - -### 3. Seed User Accounts & Logins -On startup, the system seeds accounts with their default passwords: -* **Faculty Member:** `faculty@rit.edu` / `faculty123` -* **HOD:** `hod@rit.edu` / `hod123` -* **Principal:** `principal@rit.edu` / `principal123` -* **Placement Officer:** `placement@rit.edu` / `placement123` -* **Administrator:** `admin@rit.edu` / `admin123` diff --git a/RIT-EMS-main/PROJECT_OVERVIEW.md b/RIT-EMS-main/PROJECT_OVERVIEW.md deleted file mode 100644 index 90f419d..0000000 --- a/RIT-EMS-main/PROJECT_OVERVIEW.md +++ /dev/null @@ -1,299 +0,0 @@ -# RIT Event Management System (EMS) - Project Overview & Site Map - -This document provides a comprehensive technical overview of the RIT Event Management System (EMS). It details the core goals, features, technology stack, database architecture, directory layout, and a functional site map. - -This file is structured specifically to allow developers and agentic AI systems to decode and understand the system perfectly. - ---- - -## 1. Project Goal & Context - -The **RIT Event Management System (EMS)** is a unified platform developed for Rajalakshmi Institute of Technology (RIT) to manage, propose, audit, approve, and automate institutional events. Events range from academic workshops and guest lectures to placement drives, cultural events, and sports activities. - -The system addresses critical administrative bottlenecks such as: -1. **Venue Conflicts:** Preventing overlapping bookings for key venues (e.g., auditoriums, seminar halls, computer labs). -2. **Multi-tier Approvals:** Routing proposals through HODs and the Principal based on roles, departments, and event categories. -3. **Semester Scheduling:** Transitioning calendar plans from one semester to the next with minimal manual effort. -4. **Data Aggregation:** Importing bulk event plans directly from external sources (such as Google Form spreadsheet responses). - ---- - -## 2. Technology Stack - -### Backend -* **Core Backend Service:** Firebase (Firestore Database, Firebase Authentication) -* **API Architecture:** Serverless client-side interceptor via `firebaseBackend.ts` which intercepts `/api/*` requests in the browser and processes them directly against Firestore collections. -* **Database:** Cloud Firestore (Collections: `ems_users`, `ems_events`, `ems_notes`, `ems_classes`) -* **Security:** Checked via frontend role verification and Firestore Security Rules. - -### Frontend -* **Core Framework:** React 19, TypeScript, Vite -* **Routing & State:** Component/Context state driving dynamic view rendering in a single-page application (SPA) shell -* **Styling:** Tailwind CSS, custom Vanilla CSS tokens, modern glassmorphism aesthetic -* **Animations:** Framer Motion (for smooth layout and viewport transitions) -* **Icons:** Lucide React -* **Utility Libraries:** - * `date-fns` for robust date comparisons and timeline layouts - * `xlsx` for parsing spreadsheet files (.xlsx/.csv) in-browser - ---- - -## 3. Database Schema & Architecture - -The system contains four principal Firestore collections. - -### A. User Entity (`users`) -Holds institutional account profiles, login credentials, permissions, and roles. -* `id` (Long, PK): Auto-incremented identifier. -* `email` (String, Unique): Institutional email (e.g., `@rit.edu` or `@ritindia.edu`). -* `password` (String): BCrypt hashed passcode. -* `fullName` (String): User's display name. -* `role` (String): Access levels: `ADMIN`, `PRINCIPAL`, `HOD`, `FACULTY`, `PLACEMENT`. -* `department` (String): E.g., `CSE`, `AI&ML`, `ECE`, `H&S Dept`, etc. -* `isClubCoordinator` (Boolean): Grants authorization to manage student club events. -* `isPlacementStaff` (Boolean): Grants authority to propose overriding placement activities. -* `isClassIncharge` (Boolean): Grants class representative dashboard view. -* `classStrength` (Integer): Total student count for incharge class. -* `inchargeClass` / `inchargeBatch` / `inchargeSection` (String): Targeted class details. -* `assignedClubs` (ElementCollection): List of student clubs the user is permitted to coordinate. - -### B. Event Entity (`events`) -Models event proposals, scheduling, requirements, and life-cycles. -* `id` (Long, PK) -* `title` (String, Nullable=false) -* `description` (Text) -* `startDate` / `endDate` (LocalDateTime) -* `location` (String): Maps to standard venues (e.g., `GB 4th floor auditorium`, `Wozniak Auditorium`). -* `category` (String): Categories dictate processing logic: `ACADEMIC`, `CLUB`, `PLACEMENT`, `SPORTS`, `INSTITUTIONAL`. -* `type` (String): E.g., `Workshop`, `Seminar`, `Guest Lecture`, `Competition`. -* `institution` (String): `RIT` or `RSB`. -* `department` (String) -* `academicYears` (ElementCollection): List of targeted academic batches (e.g., `1st Year`, `2nd Year`). -* `targetedSections` (ElementCollection): Targeted sections (e.g., `A`, `B`). -* `status` (String): `REQUESTED` (Pending HoD review), `PENDING_PR` (Pending Principal approval), `APPROVED` (Active scheduled event), `COMPLETED` (Past event), `CANCELLED`, `HOD_REJECTED`, `PRINCIPAL_REJECTED`. -* `guestName` / `guestSocialProfile` (String) -* `requirements` (ElementCollection): Mandatory resources (e.g., `Mementos`, `Projector`, `Lunch`, `Wi-Fi`). -* `budget` (Double) -* `hasRegistrationFee` (Boolean) / `registrationFee` (Double) -* `sponsors` (ElementCollection) -* `proposer` (ManyToOne -> `User`) -* `rejectionReason` (Text) -* `groupRequestId` (String): Identifier tying grouped recurring requests. - -### C. ClassMapping Entity (`classes`) -Used for maintaining class information and batch promotions. -* `id` (Long, PK) -* `institution` (String): E.g., `RIT`, `RSB`. -* `department` (String) -* `academicYear` (String): E.g., `1st Year`, `2nd Year`, etc. -* `sections` (ElementCollection): List of section names associated with this mapping. -* `status` (String): Defaults to `Ready`. - -### D. InstitutionalNote Entity (`institutional_notes`) -Used for pinning warnings, reminders, or notifications on the main calendar. -* `id` (Long, PK) -* `content` (String, Nullable=false) -* `targetDate` (LocalDate) -* `authorName` / `authorEmail` (String) -* `createdAt` (LocalDateTime) - ---- - -## 4. Key Workflows & Backend API Endpoints - -### A. Authentication -1. **Login Flow:** User submits credentials to `POST /api/auth/login`. -2. **Matching:** The system performs database lookup and BCrypt check. -3. **Response:** A JSON representation of the logged-in User is returned (stored in `localStorage` as `ems_user`). - -### B. Event Proposal & Approval Chain -1. **Proposal submission:** Submits to `POST /api/events/propose`. -2. **Real-time Conflict Audit:** The backend executes `findConflictingEvents()` matching `location`, `institution`, and date overlaps against `APPROVED` events. - * **Placement Overriding:** If the new proposal is a `PLACEMENT` event and `cancelConflicting` is `true`, the system sets conflicting events' status to `CANCELLED` and writes a displacement reason. - * **General Conflict:** If a conflict exists and it isn't an overridden placement, a `409 Conflict` status is returned with overlap logs. -3. **Workflow Routing:** - * Proposer is **Principal** -> Auto-approved (`APPROVED`). - * Proposer is **HoD**, or event is **Club/Placement/Institutional** -> Sent straight to Principal (`PENDING_PR`). - * Proposer is **Faculty** -> Sent to HoD (`REQUESTED`). -4. **HoD Action (`POST /api/events/{id}/approve`):** Sets status to `PENDING_PR` (Principal Desk). -5. **Principal Action (`POST /api/events/{id}/approve`):** Sets status to `APPROVED`. -6. **Rejections (`POST /api/events/{id}/reject`):** Updates status to `HOD_REJECTED` or `PRINCIPAL_REJECTED` and embeds a mandatory `reason`. - -### C. Class Promotions -* `POST /api/classes/promote?institution=RIT` -* Promotes all class mappings for the specified institution: - * `1st Year` -> `2nd Year` - * `2nd Year` -> `3rd Year` - * `3rd Year` -> `4th Year` - * `4th Year` mappings are deleted (graduated). - ---- - -## 5. Directory Layout & Architecture - -### Frontend Layout -```text -frontend/src/ -├── App.tsx # Main Router shell -├── main.tsx # React Entry mount -├── App.css # Framework and styling additions -├── index.css # Core Tailwind and glassmorphism styling definitions -├── assets/ # Logos, background images -├── context/ -│ └── AuthContext.tsx # Session controller (localStorage wrapper) -├── lib/ -│ ├── config.ts # API Base URL config (http://localhost:8081) -│ └── utils.ts # Class-name merging helper (cn) -├── pages/ -│ └── LoginPage.tsx # Institutional Portal interface -└── components/ - ├── DashboardLayout.tsx # Frame containing sidebar, header, and content - ├── Sidebar.tsx # Interactive sidebar navigation (role filtered) - └── dashboard/ # Workspace Tab Components: - ├── Overview.tsx # Dashboard welcome, stats, and calendars - ├── AllEvents.tsx # Grid view and edit trigger for all system events - ├── EventProposalForm.x # Configurator for single and recurring proposals - ├── ApprovalsView.tsx # HoD/Principal checklist for pending items - ├── InstitutionalChecklist.tsx # Audit checklist of requirement fulfillments - ├── InstitutionalCalendar.tsx # Dynamic React Calendar showing notes/events - ├── VenueTimeline.tsx # Live visual scheduling chart of venue occupancies - ├── VenuesAtGlance.tsx # Today's room availability checker - ├── FacultyEventManagement.tsx # Faculty personal dashboard view - ├── PrincipalMasterChecklist.x # Checklist of all active requirements - ├── ClubInstitutionalChecklist.x # Special checklist for Student Clubs - ├── AutomationView.tsx # Semester Swap automation dashboard - ├── ExcelImport.tsx # Bulk spreadsheet spreadsheet import tool - ├── UserManagement.tsx # Admin credentials manager - ├── ClassManagement.tsx # Admin class config manager - ├── EventDetailsModal.tsx # Detailed view overlays - └── Pagination.tsx # Table list page controllers -``` - ---- - -## 6. Functional Site Map (Page Router Decodes) - -The following map defines frontend routes, navigation identifiers, role restrictions, and the underlying controllers/endpoints. - -```mermaid -graph TD - Login[LoginPage.tsx] -->|Auth Success| Dashboard[App.tsx Dashboard Shell] - - subgraph Dashboard Views - OverviewView[Overview.tsx
Dashboard Option] - ProposalView[EventProposalForm.tsx
Propose Option] - ApprovalsView[ApprovalsView.tsx
Approvals Option] - AllEventsView[AllEvents.tsx
All Events Option] - ChecklistView[InstitutionalChecklist.tsx
Checklist Option] - HistoryView[EventHistory.tsx
History Option] - ClubsView[ClubInstitutionalChecklist.tsx
Clubs Option] - AutomationView[AutomationView.tsx
Automation Option] - ExcelImportView[ExcelImport.tsx
Excel Import Option] - ClassesView[ClassManagement.tsx
Classes Option] - UsersView[UserManagement.tsx
Manage Users Option] - end - - classDef roleAll fill:#e0f7fa,stroke:#00acc1,stroke-width:1px; - classDef roleStaff fill:#e8eaf6,stroke:#3f51b5,stroke-width:1px; - classDef roleApprover fill:#fff3e0,stroke:#ff9800,stroke-width:1px; - classDef roleAdmin fill:#fbe9e7,stroke:#ff5722,stroke-width:1px; - - class OverviewView,ProposalView,AllEventsView,ChecklistView,HistoryView roleAll; - class ClubsView roleStaff; - class ApprovalsView,AutomationView roleApprover; - class ClassesView,UsersView,ExcelImportView roleAdmin; -``` - -### Route-by-Route Specification - -#### 1. Login Gate -* **Component:** `LoginPage.tsx` -* **Route Logic:** Rendered if `isAuthenticated` is `false`. -* **Access:** Public. -* **Backend Interaction:** `POST /api/auth/login` - -#### 2. Overview Dashboard (`dashboard`) -* **Component:** `Overview.tsx` -* **Access:** All Authenticated Users. -* **Contextual Features:** - * **Principal Desk:** Shows `PrincipalMasterChecklist` (auditing table). - * **Class Incharge Desk:** Shows current class details and a form to submit class strength updates via `PUT /api/admin/users/{id}`. - * **Faculty Desk:** Shows `FacultyEventManagement` (table of personal proposed events, status, edit buttons). - * **Live Analytics:** Renders circular progress counters matching categories (Academic, Cultural, Placement, Sports, Other). -* **Embedded Sub-Components:** - * `InstitutionalCalendar.tsx` (Grid of events, notes fetching from `GET /api/notes`, notes creation via `POST /api/notes`). - * `VenuesAtGlance.tsx` (Highlights venue reservation blocks). - * `VenueTimeline.tsx` (Hour-by-hour calendar lines for room allocations). -* **Backend Interaction:** `GET /api/events`, `GET /api/notes`, `POST /api/notes` - -#### 3. Propose Event (`propose`) -* **Component:** `EventProposalForm.tsx` -* **Access:** `FACULTY`, `HOD`, `PRINCIPAL`, `PLACEMENT`, `ADMIN`. -* **Features:** Form requesting Title, Start/End DateTime, Location, Category (Academic, Club, Placement, Sports), Type (Workshop, Seminar, etc.), targeted Academic Years & Sections, Guest details, budget details, sponsors, and checklist requirements. -* **Modes:** Handles new proposals, recurring group proposals, and edit modes (loading existing values into form inputs). -* **Backend Interaction:** `POST /api/events/propose`, `PUT /api/events/{id}` - -#### 4. Approvals (`approvals`) -* **Component:** `ApprovalsView.tsx` -* **Access:** `HOD`, `PRINCIPAL`. -* **Features:** Lists all events where status is: - * `REQUESTED` (If role is `HOD`) - * `PENDING_PR` (If role is `PRINCIPAL`) -* **Actions:** Approve triggers `POST /api/events/{id}/approve?userId={id}`. Reject opens a modal requesting description and triggers `POST /api/events/{id}/reject?userId={id}`. -* **Backend Interaction:** `GET /api/events`, `POST /api/events/{id}/approve`, `POST /api/events/{id}/reject` - -#### 5. Clubs (`clubs`) -* **Component:** `ClubInstitutionalChecklist.tsx` -* **Access:** Users with `isClubCoordinator = true` or `role = ADMIN`. -* **Features:** Lists current club activity proposals and maps checklists for student societies. -* **Backend Interaction:** `GET /api/events` - -#### 6. All Events (`events`) -* **Component:** `AllEvents.tsx` -* **Access:** All Authenticated Users. -* **Features:** Tabulated search dashboard filtering all system events (Upcoming vs. Finished). Allows editing events (via Propose Event view) if the user is the proposer or an administrator. -* **Backend Interaction:** `GET /api/events` - -#### 7. Institutional Checklist (`checklist`) -* **Component:** `InstitutionalChecklist.tsx` -* **Access:** All Authenticated Users. -* **Features:** Generates a checklist report detailing logistics (Catering, venue prep, Wi-Fi configuration, etc.) for upcoming events. -* **Backend Interaction:** `GET /api/events` - -#### 8. Event History (`history`) -* **Component:** `EventHistory.tsx` -* **Access:** All Authenticated Users. -* **Features:** Searchable catalog of past completed events with analytics summaries and export tools. -* **Backend Interaction:** `GET /api/events` - -#### 9. Automation Console (`automation`) -* **Component:** `AutomationView.tsx` -* **Access:** `HOD`, `PRINCIPAL`, `ADMIN`. -* **Features:** - * **Semester Swap:** Selects source Institution/Dept/Batch (e.g. RIT CSE 3rd Year) and target Institution/Dept/Batch. Simulates calendar shifts (+/- 6 months). - * **Conflict Analysis:** Performs live in-memory evaluation for weekend events (recommends quick-shifting to Friday or Monday) and database overlaps. - * **Review Gate:** Displays simulated changes in a modal allowing the operator to Commit, Reschedule, or Skip. Committing makes a batch API request. -* **Backend Interaction:** `GET /api/events`, `POST /api/events/batch-create` - -#### 10. Excel Import (`import-excel`) -* **Component:** `ExcelImport.tsx` -* **Access:** `ADMIN` (and accessible from Dashboard views). -* **Features:** - * **Fuzzy Parsing:** Converts excel columns (Form Responses) into structured Event payloads. - * **Auto-Registration:** Identifies if the listed proposer does not exist in the user database. If missing, registers a new account (`password` defaults to `Password@123`) using the `POST /api/admin/users` service. - * **Conflict Solver:** Identifies venue/timing conflicts. Suggests moving to alternative venues or shifting times. -* **Backend Interaction:** `GET /api/events`, `GET /api/admin/users`, `POST /api/admin/users`, `POST /api/events/batch-create` - -#### 11. Class Configurations (`classes`) -* **Component:** `ClassManagement.tsx` -* **Access:** `ADMIN`. -* **Features:** - * Configures class metadata (Institution, Department, Academic Year, Sections). - * **Yearly Promotion:** Promotes student batches via a quick action (e.g. promoting 1st Years to 2nd Years, deleting graduating 4th Years). -* **Backend Interaction:** `GET /api/classes`, `POST /api/classes`, `DELETE /api/classes/{id}`, `POST /api/classes/promote` - -#### 12. User Management (`user-management`) -* **Component:** `UserManagement.tsx` -* **Access:** `ADMIN`. -* **Features:** Add new users, edit existing user profile fields (including modifying student club assignments and Class Incharge details), delete accounts, or change passcodes. -* **Backend Interaction:** `GET /api/admin/users`, `POST /api/admin/users`, `PUT /api/admin/users/{id}`, `DELETE /api/admin/users/{id}` diff --git a/RIT-EMS-main/frontend/.gitignore b/RIT-EMS-main/frontend/.gitignore deleted file mode 100644 index a547bf3..0000000 --- a/RIT-EMS-main/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/RIT-EMS-main/frontend/Hall Booking & Event Requirements 2024 (Responses).xlsx b/RIT-EMS-main/frontend/Hall Booking & Event Requirements 2024 (Responses).xlsx deleted file mode 100644 index e9a3c86..0000000 Binary files a/RIT-EMS-main/frontend/Hall Booking & Event Requirements 2024 (Responses).xlsx and /dev/null differ diff --git a/RIT-EMS-main/frontend/README.md b/RIT-EMS-main/frontend/README.md deleted file mode 100644 index 7dbf7eb..0000000 --- a/RIT-EMS-main/frontend/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# React + TypeScript + Vite - -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. - -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs) -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) - -## React Compiler - -The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: - -```js -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - - // Remove tseslint.configs.recommended and replace with this - tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - tseslint.configs.stylisticTypeChecked, - - // Other configs... - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` - -You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: - -```js -// eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' - -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - // Enable lint rules for React - reactX.configs['recommended-typescript'], - // Enable lint rules for React DOM - reactDom.configs.recommended, - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` diff --git a/RIT-EMS-main/frontend/eslint.config.js b/RIT-EMS-main/frontend/eslint.config.js deleted file mode 100644 index 5e6b472..0000000 --- a/RIT-EMS-main/frontend/eslint.config.js +++ /dev/null @@ -1,23 +0,0 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' -import { defineConfig, globalIgnores } from 'eslint/config' - -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - js.configs.recommended, - tseslint.configs.recommended, - reactHooks.configs.flat.recommended, - reactRefresh.configs.vite, - ], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - }, -]) diff --git a/RIT-EMS-main/frontend/excel_preview.csv b/RIT-EMS-main/frontend/excel_preview.csv deleted file mode 100644 index 1e6c4af..0000000 --- a/RIT-EMS-main/frontend/excel_preview.csv +++ /dev/null @@ -1,15 +0,0 @@ -Timestamp,Date of the event (start date),Date of the event (End date),starting Time,ending Time,Venue,Department,Requirements [Row 1],ending Time.1,Name of the event,Name of the faculty coordinator,Name of the Guest,Email Address,"Any Other Requirements, Please mention",Name of the faculty coordinator.1,Date of the event (End date).1,Status -2024-03-08 14:26:41.487,3/22/0024,,15:00:00,15:00:00,Wozniak Auditorium,RSB,"Memento, Projector, Mike, Refreshments",15:00:00,Biz-analytix guest lecture,,Mr Gokul Palani,badri.toppur@gmail.com,"pointer. cab for pickup and drop-off. Lunch for seven club members, and boquet.",,, -2024-07-05 12:03:24.523,1983-12-07 00:00:00,,15:00:00,15:00:00,Wozniak Auditorium,RIT Placement,"Memento, Projector, Mike, White Board, Refreshments, Lunch, Breakfast, Guest Transport (Transport Form to be submitted)",15:00:00,JP,,JP GANTHI,training@ritchennai.edu.in,,Pandithurai ,, -2024-01-23 00:00:00.000,2024-01-23 00:00:00,,11:00:00,11:00:00,Wozniak Auditorium,RSB,"2. Audio/Video, PA system, Uninterrupted power supply -3.LED Screen -4. Flower decoration -5. Computer lab with 65 systems with webcam and wifi connection. -6.Board Room for two days (stationery required) -7. Guest hospitality(Lunch & Refreshments for 8 people - Tea,Coffee, Juice, Cookies, Special Lunch) -8. Bouquets - 5 -9. Transportation for Guest - (would intimate numbers once confirmed)",11:00:00,Mindsprint Campus Placement,,,,,,, -,2024-01-23 00:00:00,,15:00:00,15:00:00,Wozniak Auditorium,RSB,"1. Wozniak auditorium -2. Lunch - 4 (2 guests, Director and Faculty) -3. Memento - 2 guests",15:00:00,"guest lecture from CII, Logistics Center of Excellence, IIT Madras",,,,,,, -2024-01-22 12:33:45.130,2024-01-23 00:00:00,,15:00:00,15:00:00,Steve Jobs 1st Floor,RIT Mech,"Projector, White Board",15:00:00,Awareness session on Start - up and chatGpt,,"Internal faculties (Dr. V.M. Gopinath, Dr.M.Shaju and Dr.M.Dinesh Babu)",pragadish.n@ritchennai.edu.in,,,, diff --git a/RIT-EMS-main/frontend/fix_urls.py b/RIT-EMS-main/frontend/fix_urls.py deleted file mode 100644 index ddce66b..0000000 --- a/RIT-EMS-main/frontend/fix_urls.py +++ /dev/null @@ -1,36 +0,0 @@ -import os -import re - -api_import = "import { API_BASE_URL } from '../../lib/config';" -# Need to adjust depth based on file location -# But I can just use a relative path that works for most components - -def fix_file(path): - with open(path, 'r') as f: - content = f.read() - - # Calculate depth for import - rel_path = os.path.relpath('src/lib/config.ts', os.path.dirname(path)) - rel_path = rel_path.replace('.ts', '').replace('\\', '/') - if not rel_path.startswith('.'): - rel_path = './' + rel_path - - import_line = f"import {{ API_BASE_URL }} from '{rel_path}';" - - # Replace the messy strings - new_content = content.replace("'http://' + window.location.hostname + ':8080", "API_BASE_URL") - new_content = new_content.replace("`http://' + window.location.hostname + ':8080", "`${API_BASE_URL}") - - if new_content != content: - # Add import if not present - if 'API_BASE_URL' in new_content and 'import { API_BASE_URL }' not in new_content: - new_content = import_line + "\n" + new_content - - with open(path, 'w') as f: - f.write(new_content) - print(f"Fixed {path}") - -for root, dirs, files in os.walk('src'): - for file in files: - if file.endswith(('.ts', '.tsx')): - fix_file(os.path.join(root, file)) diff --git a/RIT-EMS-main/frontend/index.html b/RIT-EMS-main/frontend/index.html deleted file mode 100644 index 34ce75a..0000000 --- a/RIT-EMS-main/frontend/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - RIT EMS - Event Management System - - - - -
- - - diff --git a/RIT-EMS-main/frontend/package-lock.json b/RIT-EMS-main/frontend/package-lock.json deleted file mode 100644 index 1f67ebc..0000000 --- a/RIT-EMS-main/frontend/package-lock.json +++ /dev/null @@ -1,4808 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.0", - "dependencies": { - "@types/uuid": "^10.0.0", - "clsx": "^2.1.1", - "date-fns": "^4.1.0", - "firebase": "^12.15.0", - "framer-motion": "^12.38.0", - "html-to-image": "^1.11.13", - "html2canvas": "^1.4.1", - "jspdf": "^4.2.1", - "lucide-react": "^0.454.0", - "react": "^19.2.5", - "react-dom": "^19.2.5", - "tailwind-merge": "^3.5.0", - "uuid": "^14.0.0", - "xlsx": "^0.18.5" - }, - "devDependencies": { - "@eslint/js": "^9.39.4", - "@tailwindcss/postcss": "^4.2.4", - "@types/node": "^24.12.2", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.1", - "autoprefixer": "^10.5.0", - "eslint": "^9.39.4", - "eslint-plugin-react-hooks": "^7.1.1", - "eslint-plugin-react-refresh": "^0.5.2", - "globals": "^17.5.0", - "postcss": "^8.5.10", - "tailwindcss": "^4.2.4", - "typescript": "~6.0.2", - "typescript-eslint": "^8.58.2", - "vite": "^8.0.9" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", - "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", - "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", - "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@emnapi/core": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", - "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", - "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", - "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.7", - "debug": "^4.3.1", - "minimatch": "^3.1.5" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", - "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.14.0", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.5", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.39.4", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", - "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@firebase/ai": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/@firebase/ai/-/ai-2.13.1.tgz", - "integrity": "sha512-RhT/VViTPBSplhQSuEp62HhLvfsV+LowMh8ZUo5MMRDzG7oFtSget4Kmg5oHP50hDVyWQuQj6to9iPFEZk08Tw==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.4", - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@firebase/app-types": "0.x" - } - }, - "node_modules/@firebase/analytics": { - "version": "0.10.22", - "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.22.tgz", - "integrity": "sha512-8BSaq/QRGU1+xyi8L2PTLTJU7MH9aMA72RQdIxrbhWFauOZY9OXo8f2YDN/972xA8d588tlnNVEQ2Mo69pT9Ow==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/installations": "0.6.22", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/analytics-compat": { - "version": "0.2.28", - "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.28.tgz", - "integrity": "sha512-lIAlqUUbBu93FJMlQfslryQtBwwzdzvp23ePC6FNgymXk6Ook5v4Uvc0vdutvoIeqmyA3LfP0ZeRFK8+11kOOQ==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/analytics": "0.10.22", - "@firebase/analytics-types": "0.8.4", - "@firebase/component": "0.7.3", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/analytics-types": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.4.tgz", - "integrity": "sha512-zQ+XTgkwH6CY/eUSHJRP7e4LxM30RCxlCmob5sy2axs25GE3Ny0XdgpDscMTHHQIGqWkxPXad4w2Mw9sCgT8zQ==", - "license": "Apache-2.0" - }, - "node_modules/@firebase/app": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.15.0.tgz", - "integrity": "sha512-soIskolmGgbpi0K/MfrjtdpO1220qRCbXA4Z8Qx3lM+fVwA3q40m+OM+7zBHd2nuQCrLXb33L6Oc1aBH3Y26AQ==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "idb": "7.1.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@firebase/app-check": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.12.0.tgz", - "integrity": "sha512-wMeT6HLWRAuW7Cp/5UjWBGKgjPNxWNOoNf4PRIv0weljoGMZVeqbUY7wNBWTI2/31cX1NlXx8gQruDLsUShB3Q==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/app-check-compat": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.4.5.tgz", - "integrity": "sha512-JI17mVcZs34zO6ZeSCrw4U2iohqy+n6GIzkbmsA+TbVjmvFLkUKt3bs5M+qRBteQm/0IWzqSHYFzEQLzDTQebg==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-check": "0.12.0", - "@firebase/app-check-types": "0.5.4", - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/app-check-interop-types": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.4.tgz", - "integrity": "sha512-zz3i6e13B8BfWiLy8MABtTh8aGIACgKbf9UVnyHcWs+yQzJXgQcl8A46b0zfaiJHdQ+niF0ouAfcpuf+3LMPQg==", - "license": "Apache-2.0" - }, - "node_modules/@firebase/app-check-types": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.4.tgz", - "integrity": "sha512-xV7JsIyzVr15aA7f3Pi0rB9gdBuVubs89FGA8VkRYA4g0l78poADgdfrScgf7NndSg9mm7cR7PJyY0+t22KaGw==", - "license": "Apache-2.0" - }, - "node_modules/@firebase/app-compat": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.14.tgz", - "integrity": "sha512-rgFmiofYsdS9ZG/Bht3OBxJtPD3zWE1cffShWubEm+4+qZeyzCbmtb1q6jOEjN9fB7uufe4rQmWOPXouR3758Q==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app": "0.15.0", - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@firebase/app-types": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.5.tgz", - "integrity": "sha512-YevqTjvo7Iujsa9Dwowmd6dSoElhzmD63ZSrq6bzjvQ6POjYgNjOFHLmNIgJs48eNO093NCERibuFnxbfOvU7A==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/logger": "0.5.1" - } - }, - "node_modules/@firebase/auth": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.13.3.tgz", - "integrity": "sha512-bqiq4uubDN2YyQkdvSWPQeJyXAv2O76ImF41En9b6UhV5JuBVYDoHYrrrE3NzIuGkpFMKagfhMRP4Vz6t+yQSQ==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x", - "@react-native-async-storage/async-storage": "^2.2.0 || ^3.0.0" - }, - "peerDependenciesMeta": { - "@react-native-async-storage/async-storage": { - "optional": true - } - } - }, - "node_modules/@firebase/auth-compat": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.6.8.tgz", - "integrity": "sha512-llcBREUC4iSNKZ6rvwud7Oz9Q7aAWU6KuQLa6pdu7Q+QAQsy4JLw6yFgxwtmzabsgznHmmcsX2UjHLLzqUxi3Q==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/auth": "1.13.3", - "@firebase/auth-types": "0.13.1", - "@firebase/component": "0.7.3", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/auth-interop-types": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.5.tgz", - "integrity": "sha512-1Li/YuBDBAXcKv7BzY4U28gontUmAaw53sYiqbaVOMCFb2lFKK/c3CGMUWqtwe7+TXrl3poWnTCL5umYBg85Eg==", - "license": "Apache-2.0" - }, - "node_modules/@firebase/auth-types": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.13.1.tgz", - "integrity": "sha512-0c1Mnid0uMDfGJHeUS4zfvBa4/CedJXotGy/n/NZJnBjwiJawt0ZYU+wH2VAVLiRCEfG2ncCkAX3yd1/2nrB7g==", - "license": "Apache-2.0", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" - } - }, - "node_modules/@firebase/component": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.3.tgz", - "integrity": "sha512-wFofIaa2879ogD/WvkjYXJxRmfnL0scen6ORgaC3na1FNOR9ASIUANQdhqQcmWu/h77/pVHY7ch5flewa5Bcew==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@firebase/data-connect": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.7.1.tgz", - "integrity": "sha512-2LbUU8mmSA63HknxQMmWHjpzuNLBKflvVwQc2tpoVKg0biWleNEJX031ELks0vzFs+dDjOUkCJR72RP6mQHFOg==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/auth-interop-types": "0.2.5", - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/database": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.1.3.tgz", - "integrity": "sha512-XwWCa+E4TvNGpGwXrycLRNfdogADwFcvuhyow6wDWma9W54roaQIhe+4PM0KiLsIftBdSCGI7OKCXrdSRHbIhw==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.4", - "@firebase/auth-interop-types": "0.2.5", - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "faye-websocket": "0.11.4", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@firebase/database-compat": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.1.4.tgz", - "integrity": "sha512-3pK35F1MAgmqFJQlf2nhQl44vtAXQO1uaCaQOEUI9kCRtLFqi7N+QRKR7lFZPg+xIZIyubgxQaxY69YgfZRZWg==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/database": "1.1.3", - "@firebase/database-types": "1.0.20", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@firebase/database-types": { - "version": "1.0.20", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.20.tgz", - "integrity": "sha512-kegbOk/w8iU64pr0q6k2ItyNGjnQBMHFhwS7ohdWI4W+pc0/zhhdGXTdFj6X1oxItRjPoYOsSQmERgBkn/ihxw==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-types": "0.9.5", - "@firebase/util": "1.15.1" - } - }, - "node_modules/@firebase/firestore": { - "version": "4.16.0", - "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.16.0.tgz", - "integrity": "sha512-qdHMHMvMr0nRMuZyWNR/ArWa0YlPE3C4eAbmxTASJMYXAesKPL0Y54p70moggrNPzaK7MSIIq5RDJJyntQyIYA==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "@firebase/webchannel-wrapper": "1.0.6", - "@grpc/grpc-js": "~1.9.0", - "@grpc/proto-loader": "^0.7.8", - "re2js": "^0.4.2", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/firestore-compat": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.4.11.tgz", - "integrity": "sha512-W7o1WdwWq5aABK5Up2ncSvTQs/QGLR/fy7cVpFBNqhsXtxoMtflHf2xBIG6+aoptcuGAobddq4g2Sq27wqHaYw==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/firestore": "4.16.0", - "@firebase/firestore-types": "3.0.4", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/firestore-types": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.4.tgz", - "integrity": "sha512-jGn+JSS4X9zZsrfu7Yw66v5YRdOLD1oyQh4USR0xWl4CUqV/DA6bNIXRPpxH/cUl3iVTNiP6MN7g+EL42A4qfA==", - "license": "Apache-2.0", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" - } - }, - "node_modules/@firebase/functions": { - "version": "0.13.5", - "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.13.5.tgz", - "integrity": "sha512-bWCx713f4kE/uFV7gdFOLBS7lDoiZj48MRkbAqe35gkXcCeWF4QjRNO07Jhmve7EJIoQOBczL29y2r8VRuN1kw==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/app-check-interop-types": "0.3.4", - "@firebase/auth-interop-types": "0.2.5", - "@firebase/component": "0.7.3", - "@firebase/messaging-interop-types": "0.2.5", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/functions-compat": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.4.5.tgz", - "integrity": "sha512-10qlUXGY25G5/1g9UihqksPp2po+ZqSE7LEizsrdUP7vrTmkysXxGSZCDyojSEp6mQe/ecRDdDDI+z4XRdb4wQ==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/functions": "0.13.5", - "@firebase/functions-types": "0.6.4", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/functions-types": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.4.tgz", - "integrity": "sha512-zV6kgqtduR4rUAdC/ilS7kmb93XD7bEZoJDlVBZqlOw2uGGGCNBQBuleww2rr0Ulr3L9o2TDjumEt68/l1f9DQ==", - "license": "Apache-2.0" - }, - "node_modules/@firebase/installations": { - "version": "0.6.22", - "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.22.tgz", - "integrity": "sha512-ef6nn3GGQTdReCfotRMG77PJZu8CqEbiK5pEoBnM0gTu/Z9v0i/az2p3HABsa/1beQmmyh1OsOjf7P5+pgwdZw==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/util": "1.15.1", - "idb": "7.1.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/installations-compat": { - "version": "0.2.22", - "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.22.tgz", - "integrity": "sha512-C/zpAuTP5S9OgKSPvXRupw3hoY/JZSlA1wFjD/Sb7LIQE0FNbcMdO8Y4KXVEkjVzma/DDDDIAzxEXqKMAzc88w==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/installations": "0.6.22", - "@firebase/installations-types": "0.5.4", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/installations-types": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.4.tgz", - "integrity": "sha512-U2eFapdHwjb43Vx9o+Pmj4dFfvcHEK1IirEFLqMtWrTHvmdrS3gBpBD1kmJk/9HjsOtoHZxJ2Paoe79e+L1ZPg==", - "license": "Apache-2.0", - "peerDependencies": { - "@firebase/app-types": "0.x" - } - }, - "node_modules/@firebase/logger": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.1.tgz", - "integrity": "sha512-vZKLsqE1ABOy8OjQiE7cUTFn4gvaqlk88yp8N94Pk/sDpq61YqZGqmVFZTvOyflTwuYFcWirBdYGoJgbDaXKYQ==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@firebase/messaging": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.13.0.tgz", - "integrity": "sha512-GZoo0uGRvEbszo83xcgbjJp4FpkmBEr4l8Z4hi8gl+P1Spn/MTK3HapanMzSX4yUHuTEiF5hasWRxOaz+o5sxQ==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/installations": "0.6.22", - "@firebase/messaging-interop-types": "0.2.5", - "@firebase/util": "1.15.1", - "idb": "7.1.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/messaging-compat": { - "version": "0.2.27", - "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.27.tgz", - "integrity": "sha512-JNOiu1PPgdHzEPEtoFiNxQuu0x9bm4bfETSQCpGfcTlgWkhlSK7uh7nlsjC10TQLUNgYetLmuutaYTh8aeYLVA==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/messaging": "0.13.0", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/messaging-interop-types": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.5.tgz", - "integrity": "sha512-tUEKnaAP2Y/MNIqgnriPpV6e5l13Vs/+p2yrd6NGlncPJT9O3a8muYZtdnWe+IJ4fgKLHJVC79n/asxk/N5Msw==", - "license": "Apache-2.0" - }, - "node_modules/@firebase/performance": { - "version": "0.7.12", - "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.12.tgz", - "integrity": "sha512-fe7nV8teUU3OBHlMUZ9Lw4gLhCW2k4m5Uc3pfWGV+fl8uwJQBGp9Q3lqsJ+HSrFu3Q2pJyLAgrClPGSKyDeYgQ==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/installations": "0.6.22", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0", - "web-vitals": "^4.2.4" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/performance-compat": { - "version": "0.2.25", - "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.25.tgz", - "integrity": "sha512-q6NjTXpIPoFuUmCmMN/maCdTgzT6aExs9xZo+PxfVLj6uLVGvpyAD6XWjmcrb7jChsFBYbq7E5dyNDF7Zhy9kA==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/performance": "0.7.12", - "@firebase/performance-types": "0.2.4", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/performance-types": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.4.tgz", - "integrity": "sha512-kJSEk7b0uhpcPRyL4SQ/GPujLqk52XNKcXlnsKDbWGAb9vugcLvOU3u6zfEdwd+d8hWJb5S5ZizV1JFFI0nkKg==", - "license": "Apache-2.0" - }, - "node_modules/@firebase/remote-config": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.8.5.tgz", - "integrity": "sha512-zb+7CDGFP2wYVF1LXQoYIFdoESIQM3p0+uiW1welw8+zvDxAL50K75PKTXXtunJADUrksTVpV7mD0pn54vzJRA==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/installations": "0.6.22", - "@firebase/logger": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/remote-config-compat": { - "version": "0.2.26", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.26.tgz", - "integrity": "sha512-uC57Tc7GYYOCnMgLkGIVf999XlaYaPDONoa54c93YTKDctlvCZI89z0zQ2RbhGR8Zf+QuCbQHs/99vqoE84a7g==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/logger": "0.5.1", - "@firebase/remote-config": "0.8.5", - "@firebase/remote-config-types": "0.5.1", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/remote-config-types": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.5.1.tgz", - "integrity": "sha512-cX/1LT6KQwkXzck2eSzeKnuvXZCyr8qaPpDcikoJs7jmI+oBOXixpDLeDtWj1U6GNMkIoXrEDNoyT2Ypcyp5/A==", - "license": "Apache-2.0" - }, - "node_modules/@firebase/storage": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.14.3.tgz", - "integrity": "sha512-YX4/YL6P6/fufSSeGnVhjWddcIXbFq2cWIhMKFTZo1E/Rtcl2mJj/BYUQTwJfcE1Tl8un1FOya4L05jcSLN/Eg==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app": "0.x" - } - }, - "node_modules/@firebase/storage-compat": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.4.3.tgz", - "integrity": "sha512-gruVqjtUGX8tEoeNbaWXZm0Zfcfcb7fvmDmBxV8yPAbWvExRnZYLO2+qw9idxNE7BvPXt5csyjSYHy//dAizxw==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/component": "0.7.3", - "@firebase/storage": "0.14.3", - "@firebase/storage-types": "0.8.4", - "@firebase/util": "1.15.1", - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "@firebase/app-compat": "0.x" - } - }, - "node_modules/@firebase/storage-types": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.4.tgz", - "integrity": "sha512-BT7cwxJOx8SWwlQfrlC+bD/Sk3Cw+1odCi8UZNFNWTVZoPsBnA5W+mqtZzVnvsdJpXCFGSGQ7R7vOR6dtM/BRA==", - "license": "Apache-2.0", - "peerDependencies": { - "@firebase/app-types": "0.x", - "@firebase/util": "1.x" - } - }, - "node_modules/@firebase/util": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.15.1.tgz", - "integrity": "sha512-LUdM4Wg7YM9Pq/49nGYySJA0CSQEKnGffFzWV8+6gXN7mGxn+FL1IqvFbuZUtAQcfZgHYDwCE1wwlK7rB7gl2g==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.1.0" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@firebase/webchannel-wrapper": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.6.tgz", - "integrity": "sha512-Vr/Mqu79dMwGRAyGbJ4uN4+BtXB3/mRTdzetD1daWNeG8QaWuzhhbG77GltO5c0yYmYls8i250iX73624GJd7Q==", - "license": "Apache-2.0" - }, - "node_modules/@grpc/grpc-js": { - "version": "1.9.16", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.16.tgz", - "integrity": "sha512-wE4Ut/olIzfKqp631XrG+wbF0v1vWFN4YL9FyXC2LJiG33DsV7PLzURjrCvY/6je2ntdRkeLpPDluzSRGaVltQ==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/proto-loader": "^0.7.8", - "@types/node": ">=12.12.47" - }, - "engines": { - "node": "^8.13.0 || >=10.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", - "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", - "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/types": "^0.15.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", - "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.2", - "@humanfs/types": "^0.15.0", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/types": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", - "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" - } - }, - "node_modules/@oxc-project/types": { - "version": "0.126.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.126.0.tgz", - "integrity": "sha512-oGfVtjAgwQVVpfBrbtk4e1XDyWHRFta6BS3GWVzrF8xYBT2VGQAk39yJS/wFSMrZqoiCU4oghT3Ch0HaHGIHcQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", - "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz", - "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz", - "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", - "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", - "license": "BSD-3-Clause" - }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.16.tgz", - "integrity": "sha512-rhY3k7Bsae9qQfOtph2Pm2jZEA+s8Gmjoz4hhmx70K9iMQ/ddeae+xhRQcM5IuVx5ry1+bGfkvMn7D6MJggVSA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.16.tgz", - "integrity": "sha512-rNz0yK078yrNn3DrdgN+PKiMOW8HfQ92jQiXxwX8yW899ayV00MLVdaCNeVBhG/TbH3ouYVObo8/yrkiectkcQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.16.tgz", - "integrity": "sha512-r/OmdR00HmD4i79Z//xO06uEPOq5hRXdhw7nzkxQxwSavs3PSHa1ijntdpOiZ2mzOQ3fVVu8C1M19FoNM+dMUQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.16.tgz", - "integrity": "sha512-KcRE5w8h0OnjUatG8pldyD14/CQ5Phs1oxfR+3pKDjboHRo9+MkqQaiIZlZRpsxC15paeXme/I127tUa9TXJ6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.16.tgz", - "integrity": "sha512-bT0guA1bpxEJ/ZhTRniQf7rNF8ybvXOuWbNIeLABaV5NGjx4EtOWBTSRGWFU9ZWVkPOZ+HNFP8RMcBokBiZ0Kg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.16.tgz", - "integrity": "sha512-+tHktCHWV8BDQSjemUqm/Jl/TPk3QObCTIjmdDy/nlupcujZghmKK2962LYrqFpWu+ai01AN/REOH3NEpqvYQg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.16.tgz", - "integrity": "sha512-3fPzdREH806oRLxpTWW1Gt4tQHs0TitZFOECB2xzCFLPKnSOy90gwA7P29cksYilFO6XVRY1kzga0cL2nRjKPg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.16.tgz", - "integrity": "sha512-EKwI1tSrLs7YVw+JPJT/G2dJQ1jl9qlTTTEG0V2Ok/RdOenRfBw2PQdLPyjhIu58ocdBfP7vIRN/pvMsPxs/AQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.16.tgz", - "integrity": "sha512-Uknladnb3Sxqu6SEcqBldQyJUpk8NleooZEc0MbRBJ4inEhRYWZX0NJu12vNf2mqAq7gsofAxHrGghiUYjhaLQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.16.tgz", - "integrity": "sha512-FIb8+uG49sZBtLTn+zt1AJ20TqVcqWeSIyoVt0or7uAWesgKaHbiBh6OpA/k9v0LTt+PTrb1Lao133kP4uVxkg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.16.tgz", - "integrity": "sha512-RuERhF9/EgWxZEXYWCOaViUWHIboceK4/ivdtQ3R0T44NjLkIIlGIAVAuCddFxsZ7vnRHtNQUrt2vR2n2slB2w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.16.tgz", - "integrity": "sha512-mXcXnvd9GpazCxeUCCnZ2+YF7nut+ZOEbE4GtaiPtyY6AkhZWbK70y1KK3j+RDhjVq5+U8FySkKRb/+w0EeUwA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.16.tgz", - "integrity": "sha512-3Q2KQxnC8IJOLqXmUMoYwyIPZU9hzRbnHaoV3Euz+VVnjZKcY8ktnNP8T9R4/GGQtb27C/UYKABxesKWb8lsvQ==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.9.2", - "@emnapi/runtime": "1.9.2", - "@napi-rs/wasm-runtime": "^1.1.4" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.16.tgz", - "integrity": "sha512-tj7XRemQcOcFwv7qhpUxMTBbI5mWMlE4c1Omhg5+h8GuLXzyj8HviYgR+bB2DMDgRqUE+jiDleqSCRjx4aYk/Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.16.tgz", - "integrity": "sha512-PH5DRZT+F4f2PTXRXR8uJxnBq2po/xFtddyabTJVJs/ZYVHqXPEgNIr35IHTEa6bpa0Q8Awg+ymkTaGnKITw4g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.7", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.7.tgz", - "integrity": "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tailwindcss/node": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.4.tgz", - "integrity": "sha512-Ai7+yQPxz3ddrDQzFfBKdHEVBg0w3Zl83jnjuwxnZOsnH9pGn93QHQtpU0p/8rYWxvbFZHneni6p1BSLK4DkGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/remapping": "^2.3.5", - "enhanced-resolve": "^5.19.0", - "jiti": "^2.6.1", - "lightningcss": "1.32.0", - "magic-string": "^0.30.21", - "source-map-js": "^1.2.1", - "tailwindcss": "4.2.4" - } - }, - "node_modules/@tailwindcss/oxide": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.4.tgz", - "integrity": "sha512-9El/iI069DKDSXwTvB9J4BwdO5JhRrOweGaK25taBAvBXyXqJAX+Jqdvs8r8gKpsI/1m0LeJLyQYTf/WLrBT1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 20" - }, - "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.2.4", - "@tailwindcss/oxide-darwin-arm64": "4.2.4", - "@tailwindcss/oxide-darwin-x64": "4.2.4", - "@tailwindcss/oxide-freebsd-x64": "4.2.4", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.4", - "@tailwindcss/oxide-linux-arm64-gnu": "4.2.4", - "@tailwindcss/oxide-linux-arm64-musl": "4.2.4", - "@tailwindcss/oxide-linux-x64-gnu": "4.2.4", - "@tailwindcss/oxide-linux-x64-musl": "4.2.4", - "@tailwindcss/oxide-wasm32-wasi": "4.2.4", - "@tailwindcss/oxide-win32-arm64-msvc": "4.2.4", - "@tailwindcss/oxide-win32-x64-msvc": "4.2.4" - } - }, - "node_modules/@tailwindcss/oxide-android-arm64": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.4.tgz", - "integrity": "sha512-e7MOr1SAn9U8KlZzPi1ZXGZHeC5anY36qjNwmZv9pOJ8E4Q6jmD1vyEHkQFmNOIN7twGPEMXRHmitN4zCMN03g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-arm64": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.4.tgz", - "integrity": "sha512-tSC/Kbqpz/5/o/C2sG7QvOxAKqyd10bq+ypZNf+9Fi2TvbVbv1zNpcEptcsU7DPROaSbVgUXmrzKhurFvo5eDg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-darwin-x64": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.4.tgz", - "integrity": "sha512-yPyUXn3yO/ufR6+Kzv0t4fCg2qNr90jxXc5QqBpjlPNd0NqyDXcmQb/6weunH/MEDXW5dhyEi+agTDiqa3WsGg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-freebsd-x64": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.4.tgz", - "integrity": "sha512-BoMIB4vMQtZsXdGLVc2z+P9DbETkiopogfWZKbWwM8b/1Vinbs4YcUwo+kM/KeLkX3Ygrf4/PsRndKaYhS8Eiw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.4.tgz", - "integrity": "sha512-7pIHBLTHYRAlS7V22JNuTh33yLH4VElwKtB3bwchK/UaKUPpQ0lPQiOWcbm4V3WP2I6fNIJ23vABIvoy2izdwA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.4.tgz", - "integrity": "sha512-+E4wxJ0ZGOzSH325reXTWB48l42i93kQqMvDyz5gqfRzRZ7faNhnmvlV4EPGJU3QJM/3Ab5jhJ5pCRUsKn6OQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-arm64-musl": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.4.tgz", - "integrity": "sha512-bBADEGAbo4ASnppIziaQJelekCxdMaxisrk+fB7Thit72IBnALp9K6ffA2G4ruj90G9XRS2VQ6q2bCKbfFV82g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-gnu": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.4.tgz", - "integrity": "sha512-7Mx25E4WTfnht0TVRTyC00j3i0M+EeFe7wguMDTlX4mRxafznw0CA8WJkFjWYH5BlgELd1kSjuU2JiPnNZbJDA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-linux-x64-musl": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.4.tgz", - "integrity": "sha512-2wwJRF7nyhOR0hhHoChc04xngV3iS+akccHTGtz965FwF0up4b2lOdo6kI1EbDaEXKgvcrFBYcYQQ/rrnWFVfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-wasm32-wasi": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.4.tgz", - "integrity": "sha512-FQsqApeor8Fo6gUEklzmaa9994orJZZDBAlQpK2Mq+DslRKFJeD6AjHpBQ0kZFQohVr8o85PPh8eOy86VlSCmw==", - "bundleDependencies": [ - "@napi-rs/wasm-runtime", - "@emnapi/core", - "@emnapi/runtime", - "@tybys/wasm-util", - "@emnapi/wasi-threads", - "tslib" - ], - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.8.1", - "@emnapi/runtime": "^1.8.1", - "@emnapi/wasi-threads": "^1.1.0", - "@napi-rs/wasm-runtime": "^1.1.1", - "@tybys/wasm-util": "^0.10.1", - "tslib": "^2.8.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.4.tgz", - "integrity": "sha512-L9BXqxC4ToVgwMFqj3pmZRqyHEztulpUJzCxUtLjobMCzTPsGt1Fa9enKbOpY2iIyVtaHNeNvAK8ERP/64sqGQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.4.tgz", - "integrity": "sha512-ESlKG0EpVJQwRjXDDa9rLvhEAh0mhP1sF7sap9dNZT0yyl9SAG6T7gdP09EH0vIv0UNTlo6jPWyujD6559fZvw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 20" - } - }, - "node_modules/@tailwindcss/postcss": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.2.4.tgz", - "integrity": "sha512-wgAVj6nUWAolAu8YFvzT2cTBIElWHkjZwFYovF+xsqKsW2ADxM/X2opxj5NsF/qVccAOjRNe8X2IdPzMsWyHTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "@tailwindcss/node": "4.2.4", - "@tailwindcss/oxide": "4.2.4", - "postcss": "^8.5.6", - "tailwindcss": "4.2.4" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", - "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "24.12.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.2.tgz", - "integrity": "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==", - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@types/pako": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz", - "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==", - "license": "MIT" - }, - "node_modules/@types/raf": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.3.tgz", - "integrity": "sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==", - "license": "MIT", - "optional": true - }, - "node_modules/@types/react": { - "version": "19.2.14", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", - "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", - "dev": true, - "license": "MIT", - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true - }, - "node_modules/@types/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.0.tgz", - "integrity": "sha512-HyAZtpdkgZwpq8Sz3FSUvCR4c+ScbuWa9AksK2Jweub7w4M3yTz4O11AqVJzLYjy/B9ZWPyc81I+mOdJU/bDQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.59.0", - "@typescript-eslint/type-utils": "8.59.0", - "@typescript-eslint/utils": "8.59.0", - "@typescript-eslint/visitor-keys": "8.59.0", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.59.0", - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.0.tgz", - "integrity": "sha512-TI1XGwKbDpo9tRW8UDIXCOeLk55qe9ZFGs8MTKU6/M08HWTw52DD/IYhfQtOEhEdPhLMT26Ka/x7p70nd3dzDg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.59.0", - "@typescript-eslint/types": "8.59.0", - "@typescript-eslint/typescript-estree": "8.59.0", - "@typescript-eslint/visitor-keys": "8.59.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.0.tgz", - "integrity": "sha512-Lw5ITrR5s5TbC19YSvlr63ZfLaJoU6vtKTHyB0GQOpX0W7d5/Ir6vUahWi/8Sps/nOukZQ0IB3SmlxZnjaKVnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.59.0", - "@typescript-eslint/types": "^8.59.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.0.tgz", - "integrity": "sha512-UzR16Ut8IpA3Mc4DbgAShlPPkVm8xXMWafXxB0BocaVRHs8ZGakAxGRskF7FId3sdk9lgGD73GSFaWmWFDE4dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.59.0", - "@typescript-eslint/visitor-keys": "8.59.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.0.tgz", - "integrity": "sha512-91Sbl3s4Kb3SybliIY6muFBmHVv+pYXfybC4Oolp3dvk8BvIE3wOPc+403CWIT7mJNkfQRGtdqghzs2+Z91Tqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.0.tgz", - "integrity": "sha512-3TRiZaQSltGqGeNrJzzr1+8YcEobKH9rHnqIp/1psfKFmhRQDNMGP5hBufanYTGznwShzVLs3Mz+gDN7HkWfXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.59.0", - "@typescript-eslint/typescript-estree": "8.59.0", - "@typescript-eslint/utils": "8.59.0", - "debug": "^4.4.3", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.0.tgz", - "integrity": "sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.0.tgz", - "integrity": "sha512-O9Re9P1BmBLFJyikRbQpLku/QA3/AueZNO9WePLBwQrvkixTmDe8u76B6CYUAITRl/rHawggEqUGn5QIkVRLMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.59.0", - "@typescript-eslint/tsconfig-utils": "8.59.0", - "@typescript-eslint/types": "8.59.0", - "@typescript-eslint/visitor-keys": "8.59.0", - "debug": "^4.4.3", - "minimatch": "^10.2.2", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.5.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", - "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "10.2.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", - "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "brace-expansion": "^5.0.5" - }, - "engines": { - "node": "18 || 20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.0.tgz", - "integrity": "sha512-I1R/K7V07XsMJ12Oaxg/O9GfrysGTmCRhvZJBv0RE0NcULMzjqVpR5kRRQjHsz3J/bElU7HwCO7zkqL+MSUz+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.59.0", - "@typescript-eslint/types": "8.59.0", - "@typescript-eslint/typescript-estree": "8.59.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.0.tgz", - "integrity": "sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.59.0", - "eslint-visitor-keys": "^5.0.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", - "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz", - "integrity": "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rolldown/pluginutils": "1.0.0-rc.7" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", - "babel-plugin-react-compiler": "^1.0.0", - "vite": "^8.0.0" - }, - "peerDependenciesMeta": { - "@rolldown/plugin-babel": { - "optional": true - }, - "babel-plugin-react-compiler": { - "optional": true - } - } - }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/adler-32": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", - "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/autoprefixer": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", - "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.28.2", - "caniuse-lite": "^1.0.30001787", - "fraction.js": "^5.3.4", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.20", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.20.tgz", - "integrity": "sha512-1AaXxEPfXT+GvTBJFuy4yXVHWJBXa4OdbIebGN/wX5DlsIkU0+wzGnd2lOzokSk51d5LUmqjgBLRLlypLUqInQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/browserslist": { - "version": "4.28.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", - "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.10.12", - "caniuse-lite": "^1.0.30001782", - "electron-to-chromium": "^1.5.328", - "node-releases": "^2.0.36", - "update-browserslist-db": "^1.2.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001790", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001790.tgz", - "integrity": "sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/canvg": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.11.tgz", - "integrity": "sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==", - "license": "MIT", - "optional": true, - "dependencies": { - "@babel/runtime": "^7.12.5", - "@types/raf": "^3.4.0", - "core-js": "^3.8.3", - "raf": "^3.4.1", - "regenerator-runtime": "^0.13.7", - "rgbcolor": "^1.0.1", - "stackblur-canvas": "^2.0.0", - "svg-pathdata": "^6.0.3" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/cfb": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", - "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", - "license": "Apache-2.0", - "dependencies": { - "adler-32": "~1.3.0", - "crc-32": "~1.2.0" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/codepage": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", - "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/core-js": { - "version": "3.49.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", - "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "license": "Apache-2.0", - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/css-line-break": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", - "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", - "license": "MIT", - "dependencies": { - "utrie": "^1.0.2" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/date-fns": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/dompurify": { - "version": "3.4.11", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.11.tgz", - "integrity": "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optional": true, - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.343", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.343.tgz", - "integrity": "sha512-YHnQ3MXI08icvL9ZKnEBy05F2EQ8ob01UaMOuMbM8l+4UcAq6MPPbBTJBbsBUg3H8JeZNt+O4fjsoWth3p6IFg==", - "dev": true, - "license": "ISC" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/enhanced-resolve": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.1.tgz", - "integrity": "sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.39.4", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", - "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.2", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.5", - "@eslint/js": "9.39.4", - "@eslint/plugin-kit": "^0.4.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.14.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.5", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", - "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/parser": "^7.24.4", - "hermes-parser": "^0.25.1", - "zod": "^3.25.0 || ^4.0.0", - "zod-validation-error": "^3.5.0 || ^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" - } - }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.2.tgz", - "integrity": "sha512-hmgTH57GfzoTFjVN0yBwTggnsVUF2tcqi7RJZHqi9lIezSs4eFyAMktA68YD4r5kNw1mxyY4dmkyoFDb3FIqrA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": "^9 || ^10" - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-png": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz", - "integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==", - "license": "MIT", - "dependencies": { - "@types/pako": "^2.0.3", - "iobuffer": "^5.3.2", - "pako": "^2.1.0" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "license": "Apache-2.0", - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fflate": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", - "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", - "license": "MIT" - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/firebase": { - "version": "12.15.0", - "resolved": "https://registry.npmjs.org/firebase/-/firebase-12.15.0.tgz", - "integrity": "sha512-p0YTLcRSTiBXMx9sGr4ZNSfLjc/RVBEw4C/TXjVMtw65+6E1Pbm47UY3F4/AqRoDobEcNX3gsbPGy7jPjxbgSQ==", - "license": "Apache-2.0", - "dependencies": { - "@firebase/ai": "2.13.1", - "@firebase/analytics": "0.10.22", - "@firebase/analytics-compat": "0.2.28", - "@firebase/app": "0.15.0", - "@firebase/app-check": "0.12.0", - "@firebase/app-check-compat": "0.4.5", - "@firebase/app-compat": "0.5.14", - "@firebase/app-types": "0.9.5", - "@firebase/auth": "1.13.3", - "@firebase/auth-compat": "0.6.8", - "@firebase/data-connect": "0.7.1", - "@firebase/database": "1.1.3", - "@firebase/database-compat": "2.1.4", - "@firebase/firestore": "4.16.0", - "@firebase/firestore-compat": "0.4.11", - "@firebase/functions": "0.13.5", - "@firebase/functions-compat": "0.4.5", - "@firebase/installations": "0.6.22", - "@firebase/installations-compat": "0.2.22", - "@firebase/messaging": "0.13.0", - "@firebase/messaging-compat": "0.2.27", - "@firebase/performance": "0.7.12", - "@firebase/performance-compat": "0.2.25", - "@firebase/remote-config": "0.8.5", - "@firebase/remote-config-compat": "0.2.26", - "@firebase/storage": "0.14.3", - "@firebase/storage-compat": "0.4.3", - "@firebase/util": "1.15.1" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", - "dev": true, - "license": "ISC" - }, - "node_modules/frac": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", - "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/fraction.js": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", - "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/framer-motion": { - "version": "12.38.0", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.38.0.tgz", - "integrity": "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==", - "license": "MIT", - "dependencies": { - "motion-dom": "^12.38.0", - "motion-utils": "^12.36.0", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "17.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.5.0.tgz", - "integrity": "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "dev": true, - "license": "MIT" - }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hermes-estree": "0.25.1" - } - }, - "node_modules/html-to-image": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", - "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==", - "license": "MIT" - }, - "node_modules/html2canvas": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", - "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", - "license": "MIT", - "dependencies": { - "css-line-break": "^2.1.0", - "text-segmentation": "^1.0.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", - "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", - "license": "MIT" - }, - "node_modules/idb": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", - "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", - "license": "ISC" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/iobuffer": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz", - "integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==", - "license": "MIT" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jspdf": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-4.2.1.tgz", - "integrity": "sha512-YyAXyvnmjTbR4bHQRLzex3CuINCDlQnBqoSYyjJwTP2x9jDLuKDzy7aKUl0hgx3uhcl7xzg32agn5vlie6HIlQ==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.28.6", - "fast-png": "^6.2.0", - "fflate": "^0.8.1" - }, - "optionalDependencies": { - "canvg": "^3.0.11", - "core-js": "^3.6.0", - "dompurify": "^3.3.1", - "html2canvas": "^1.0.0-rc.5" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lucide-react": { - "version": "0.454.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.454.0.tgz", - "integrity": "sha512-hw7zMDwykCLnEzgncEEjHeA6+45aeEzRYuKHuyRSOPkhko+J3ySGjGIzu+mmMfDFG1vazHepMaYFYHbTFAZAAQ==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/motion-dom": { - "version": "12.38.0", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.38.0.tgz", - "integrity": "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==", - "license": "MIT", - "dependencies": { - "motion-utils": "^12.36.0" - } - }, - "node_modules/motion-utils": { - "version": "12.36.0", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.36.0.tgz", - "integrity": "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==", - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.38", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", - "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", - "license": "(MIT AND Zlib)" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "license": "MIT", - "optional": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", - "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/protobufjs": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz", - "integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.5", - "@protobufjs/eventemitter": "^1.1.1", - "@protobufjs/fetch": "^1.1.1", - "@protobufjs/float": "^1.0.2", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.1", - "@types/node": ">=13.7.0", - "long": "^5.3.2" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "license": "MIT", - "optional": true, - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/re2js": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/re2js/-/re2js-0.4.3.tgz", - "integrity": "sha512-EuNmh7jurhHEE8Ge/lBo9JuMLb3qf866Xjjfyovw3wPc7+hlqDkZq4LwhrCQMEI+ARWfrKrHozEndzlpNT0WDg==", - "license": "MIT" - }, - "node_modules/react": { - "version": "19.2.5", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.5.tgz", - "integrity": "sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.5", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.5.tgz", - "integrity": "sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.5" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "license": "MIT", - "optional": true - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/rgbcolor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", - "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", - "license": "MIT OR SEE LICENSE IN FEEL-FREE.md", - "optional": true, - "engines": { - "node": ">= 0.8.15" - } - }, - "node_modules/rolldown": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.16.tgz", - "integrity": "sha512-rzi5WqKzEZw3SooTt7cgm4eqIoujPIyGcJNGFL7iPEuajQw7vxMHUkXylu4/vhCkJGXsgRmxqMKXUpT6FEgl0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@oxc-project/types": "=0.126.0", - "@rolldown/pluginutils": "1.0.0-rc.16" - }, - "bin": { - "rolldown": "bin/cli.mjs" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.0-rc.16", - "@rolldown/binding-darwin-arm64": "1.0.0-rc.16", - "@rolldown/binding-darwin-x64": "1.0.0-rc.16", - "@rolldown/binding-freebsd-x64": "1.0.0-rc.16", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.16", - "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.16", - "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.16", - "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.16", - "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.16", - "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.16", - "@rolldown/binding-linux-x64-musl": "1.0.0-rc.16", - "@rolldown/binding-openharmony-arm64": "1.0.0-rc.16", - "@rolldown/binding-wasm32-wasi": "1.0.0-rc.16", - "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.16", - "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.16" - } - }, - "node_modules/rolldown/node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.16", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.16.tgz", - "integrity": "sha512-45+YtqxLYKDWQouLKCrpIZhke+nXxhsw+qAHVzHDVwttyBlHNBVs2K25rDXrZzhpTp9w1FlAlvweV1H++fdZoA==", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ssf": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", - "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", - "license": "Apache-2.0", - "dependencies": { - "frac": "~1.1.2" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/stackblur-canvas": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.7.0.tgz", - "integrity": "sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.14" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/svg-pathdata": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", - "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/tailwind-merge": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz", - "integrity": "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/dcastil" - } - }, - "node_modules/tailwindcss": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.4.tgz", - "integrity": "sha512-HhKppgO81FQof5m6TEnuBWCZGgfRAWbaeOaGT00KOy/Pf/j6oUihdvBpA7ltCeAvZpFhW3j0PTclkxsd4IXYDA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tapable": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", - "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/text-segmentation": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", - "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", - "license": "MIT", - "dependencies": { - "utrie": "^1.0.2" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/ts-api-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", - "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/typescript": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", - "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "8.59.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.0.tgz", - "integrity": "sha512-BU3ONW9X+v90EcCH9ZS6LMackcVtxRLlI3XrYyqZIwVSHIk7Qf7bFw1z0M9Q0IUxhTMZCf8piY9hTYaNEIASrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.59.0", - "@typescript-eslint/parser": "8.59.0", - "@typescript-eslint/typescript-estree": "8.59.0", - "@typescript-eslint/utils": "8.59.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", - "typescript": ">=4.8.4 <6.1.0" - } - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "license": "MIT" - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/utrie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", - "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", - "license": "MIT", - "dependencies": { - "base64-arraybuffer": "^1.0.2" - } - }, - "node_modules/uuid": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz", - "integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist-node/bin/uuid" - } - }, - "node_modules/vite": { - "version": "8.0.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.9.tgz", - "integrity": "sha512-t7g7GVRpMXjNpa67HaVWI/8BWtdVIQPCL2WoozXXA7LBGEFK4AkkKkHx2hAQf5x1GZSlcmEDPkVLSGahxnEEZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.4", - "postcss": "^8.5.10", - "rolldown": "1.0.0-rc.16", - "tinyglobby": "^0.2.16" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.1.0", - "esbuild": "^0.27.0 || ^0.28.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "@vitejs/devtools": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/web-vitals": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", - "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==", - "license": "Apache-2.0" - }, - "node_modules/websocket-driver": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.5.tgz", - "integrity": "sha512-ZL2+3c7kMBdIRCMz6l8jQMHyGVxj+UL+xVk74Ombiciboca8rHa15L86B19E5oh1pL9Ii/uj54gtsIrZGMo6zA==", - "license": "Apache-2.0", - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wmf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", - "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/word": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", - "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/xlsx": { - "version": "0.18.5", - "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", - "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", - "license": "Apache-2.0", - "dependencies": { - "adler-32": "~1.3.0", - "cfb": "~1.2.1", - "codepage": "~1.15.0", - "crc-32": "~1.2.1", - "ssf": "~0.11.2", - "wmf": "~1.0.1", - "word": "~0.3.0" - }, - "bin": { - "xlsx": "bin/xlsx.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", - "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-validation-error": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", - "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "zod": "^3.25.0 || ^4.0.0" - } - } - } -} diff --git a/RIT-EMS-main/frontend/package.json b/RIT-EMS-main/frontend/package.json deleted file mode 100644 index cf7debc..0000000 --- a/RIT-EMS-main/frontend/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "lint": "eslint .", - "preview": "vite preview" - }, - "dependencies": { - "@types/uuid": "^10.0.0", - "clsx": "^2.1.1", - "date-fns": "^4.1.0", - "firebase": "^12.15.0", - "framer-motion": "^12.38.0", - "html-to-image": "^1.11.13", - "html2canvas": "^1.4.1", - "jspdf": "^4.2.1", - "lucide-react": "^0.454.0", - "react": "^19.2.5", - "react-dom": "^19.2.5", - "tailwind-merge": "^3.5.0", - "uuid": "^14.0.0", - "xlsx": "^0.18.5" - }, - "devDependencies": { - "@eslint/js": "^9.39.4", - "@tailwindcss/postcss": "^4.2.4", - "@types/node": "^24.12.2", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.1", - "autoprefixer": "^10.5.0", - "eslint": "^9.39.4", - "eslint-plugin-react-hooks": "^7.1.1", - "eslint-plugin-react-refresh": "^0.5.2", - "globals": "^17.5.0", - "postcss": "^8.5.10", - "tailwindcss": "^4.2.4", - "typescript": "~6.0.2", - "typescript-eslint": "^8.58.2", - "vite": "^8.0.9" - } -} diff --git a/RIT-EMS-main/frontend/postcss.config.js b/RIT-EMS-main/frontend/postcss.config.js deleted file mode 100644 index 14502dc..0000000 --- a/RIT-EMS-main/frontend/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - plugins: { - "@tailwindcss/postcss": {}, - autoprefixer: {}, - }, -} diff --git a/RIT-EMS-main/frontend/public/favicon.svg b/RIT-EMS-main/frontend/public/favicon.svg deleted file mode 100644 index 6893eb1..0000000 --- a/RIT-EMS-main/frontend/public/favicon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/RIT-EMS-main/frontend/public/icons.svg b/RIT-EMS-main/frontend/public/icons.svg deleted file mode 100644 index e952219..0000000 --- a/RIT-EMS-main/frontend/public/icons.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/RIT-EMS-main/frontend/public/parchment_texture.png b/RIT-EMS-main/frontend/public/parchment_texture.png deleted file mode 100644 index 6236d5a..0000000 Binary files a/RIT-EMS-main/frontend/public/parchment_texture.png and /dev/null differ diff --git a/RIT-EMS-main/frontend/public/wood_roller_texture.png b/RIT-EMS-main/frontend/public/wood_roller_texture.png deleted file mode 100644 index 02ccad9..0000000 Binary files a/RIT-EMS-main/frontend/public/wood_roller_texture.png and /dev/null differ diff --git a/RIT-EMS-main/frontend/src/App.css b/RIT-EMS-main/frontend/src/App.css deleted file mode 100644 index 0274904..0000000 --- a/RIT-EMS-main/frontend/src/App.css +++ /dev/null @@ -1,187 +0,0 @@ -.counter { - font-size: 16px; - padding: 5px 10px; - border-radius: 5px; - color: var(--accent); - background: var(--accent-bg); - border: 2px solid transparent; - transition: border-color 0.3s; - margin-bottom: 24px; - - &:hover { - border-color: var(--accent-border); - } - - &:focus-visible { - outline: 2px solid var(--accent); - outline-offset: 2px; - } -} - -.hero { - position: relative; - - .base, - .framework, - .vite { - inset-inline: 0; - margin: 0 auto; - } - - .base { - width: 170px; - position: relative; - z-index: 0; - } - - .framework, - .vite { - position: absolute; - } - - .framework { - z-index: 1; - top: 34px; - height: 28px; - transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg) scale(1.4); - } - - .vite { - z-index: 0; - top: 107px; - height: 26px; - width: auto; - transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg) scale(0.8); - } -} - -#center { - display: flex; - flex-direction: column; - gap: 25px; - place-content: center; - place-items: center; - flex-grow: 1; - - @media (max-width: 1024px) { - padding: 32px 20px 24px; - gap: 18px; - } -} - -#next-steps { - display: flex; - border-top: 1px solid var(--border); - text-align: left; - - &>div { - flex: 1 1 0; - padding: 32px; - - @media (max-width: 1024px) { - padding: 24px 20px; - } - } - - .icon { - margin-bottom: 16px; - width: 22px; - height: 22px; - } - - @media (max-width: 1024px) { - flex-direction: column; - text-align: center; - } -} - -#docs { - border-right: 1px solid var(--border); - - @media (max-width: 1024px) { - border-right: none; - border-bottom: 1px solid var(--border); - } -} - -#next-steps ul { - list-style: none; - padding: 0; - display: flex; - gap: 8px; - margin: 32px 0 0; - - .logo { - height: 25px; - } - - a { - color: var(--text-h); - font-size: 16px; - border-radius: 6px; - background: var(--social-bg); - display: flex; - padding: 6px 12px; - align-items: center; - gap: 8px; - text-decoration: none; - transition: box-shadow 0.3s; - - &:hover { - box-shadow: var(--shadow); - } - - .button-icon { - height: 18px; - width: 18px; - } - } - - @media (max-width: 1024px) { - margin-top: 20px; - flex-wrap: wrap; - justify-content: center; - - li { - flex: 1 1 calc(50% - 8px); - } - - a { - width: 100%; - justify-content: center; - box-sizing: border-box; - } - } -} - -#spacer { - height: 88px; - border-top: 1px solid var(--border); - - @media (max-width: 1024px) { - height: 48px; - } -} - -.ticks { - position: relative; - width: 100%; - - &::before, - &::after { - content: ''; - position: absolute; - top: -4.5px; - border: 5px solid transparent; - } - - &::before { - left: 0; - border-left-color: var(--border); - } - - &::after { - right: 0; - border-right-color: var(--border); - } -} \ No newline at end of file diff --git a/RIT-EMS-main/frontend/src/App.tsx b/RIT-EMS-main/frontend/src/App.tsx deleted file mode 100644 index bb64b25..0000000 --- a/RIT-EMS-main/frontend/src/App.tsx +++ /dev/null @@ -1,203 +0,0 @@ -import { API_BASE_URL } from './lib/config'; -import React, { useState } from 'react'; -import { DashboardLayout } from './components/DashboardLayout'; -import { InstitutionalChecklist } from './components/dashboard/InstitutionalChecklist'; -import { EventProposalForm } from './components/dashboard/EventProposalForm'; -import { AllEvents } from './components/dashboard/AllEvents'; -import { ApprovalsView } from './components/dashboard/ApprovalsView'; -import { UserManagement } from './components/dashboard/UserManagement'; -import { ClassManagement } from './components/dashboard/ClassManagement'; -import { LoginPage } from './pages/LoginPage'; -import { AuthProvider, useAuth } from './context/AuthContext'; -import { DialogProvider } from './context/DialogContext'; -import { motion, AnimatePresence } from 'framer-motion'; -import { StatusTimeline, type Event } from './components/dashboard/EventStatusTimeline'; -import { useEffect } from 'react'; - -import { InstitutionalCalendar } from './components/dashboard/InstitutionalCalendar'; -import { VenueTimeline } from './components/dashboard/VenueTimeline'; -import { EventHistory } from './components/dashboard/EventHistory'; -import { ClubInstitutionalChecklist } from './components/dashboard/ClubInstitutionalChecklist'; -import { AutomationView } from './components/dashboard/AutomationView'; -import { Overview } from './components/dashboard/Overview'; -import { ExcelImport } from './components/dashboard/ExcelImport'; -import { StudentDashboard } from './components/dashboard/StudentDashboard'; -import { StudentRegistrationsView } from './components/dashboard/StudentRegistrationsView'; -import { ManageNoticesView } from './components/dashboard/ManageNoticesView'; - - -const AppContent: React.FC = () => { - const { isAuthenticated, user } = useAuth(); - const isClubAuthorized = user?.isClubCoordinator || user?.role === 'ADMIN'; - const [activeItem, setActiveItem] = useState('dashboard'); - const [userEvents, setUserEvents] = useState([]); - const [preFillData, setPreFillData] = useState(null); - - const handleIncompleteClick = (data: any) => { - setPreFillData(data); - setActiveItem('propose'); - }; - - const handleCalendarPropose = (date: string) => { - setPreFillData({ startDate: `${date}T09:00` }); - setActiveItem('propose'); - }; - - const handleClubEventClick = (data: any) => { - setPreFillData(data); - setActiveItem('propose'); - }; - - const handleEditEvent = (event: any) => { - setPreFillData({ - ...event, - eventName: event.title, - venue: event.location, - socialProfile: event.guestSocialProfile, - isEditMode: true - }); - setActiveItem('propose'); - }; - - const handleSidebarClick = (item: string) => { - if (item === 'propose') setPreFillData(null); - setActiveItem(item); - }; - - useEffect(() => { - const handleNav = (e: any) => setActiveItem(e.detail); - window.addEventListener('navigate', handleNav); - return () => window.removeEventListener('navigate', handleNav); - }, []); - - - useEffect(() => { - if (isAuthenticated && activeItem === 'dashboard') { - fetch(API_BASE_URL + '/api/events') - .then(res => { - if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`); - return res.json(); - }) - .then(data => { - if (Array.isArray(data)) { - let filtered = data; - if (user?.role === 'HOD') { - const userDepts = user?.department ? user.department.split(',').map(d => d.trim().toLowerCase()) : []; - filtered = data.filter((e: Event) => userDepts.includes(e.department?.trim().toLowerCase())); - } else if (user?.role === 'FACULTY') { - filtered = data.filter((e: Event) => e.proposer?.email === user?.email); - } - setUserEvents(filtered); - } - }) - .catch(err => console.error("Failed to fetch dashboard events:", err)); - } - }, [isAuthenticated, activeItem, user?.email, user?.role, user?.department]); - - if (!isAuthenticated) { - return ( - - - - - - ); - } - - if (user?.role === 'STUDENT') { - return ( - - - - - - ); - } - - const renderContent = () => { - const isDashboard = ( - - ); - - switch (activeItem) { - case 'user-management': - return user?.role === 'ADMIN' ? : isDashboard; - case 'approvals': - return (user?.role === 'HOD' || user?.role === 'PRINCIPAL') ? : isDashboard; - case 'clubs': - return isClubAuthorized ? : isDashboard; - case 'events': - return ; - case 'propose': - return ; - case 'checklist': - return ; - case 'history': - return ; - case 'classes': - return user?.role === 'ADMIN' ? : isDashboard; - case 'automation': - return (user?.role === 'ADMIN' || user?.role === 'PRINCIPAL' || user?.role === 'HOD') ? : isDashboard; - case 'import-excel': - return ; - case 'student-registrations': - return (user?.role === 'FACULTY' || user?.role === 'HOD' || user?.role === 'ADMIN') ? : isDashboard; - case 'manage-notices': - return user?.role === 'ADMIN' ? : isDashboard; - case 'dashboard': - return isDashboard; - default: - return isDashboard; - } - }; - - return ( - - - - {renderContent()} - - - - ); -}; - -function App() { - return ( - - - - - - ); -} - -export default App; diff --git a/RIT-EMS-main/frontend/src/assets/hero.png b/RIT-EMS-main/frontend/src/assets/hero.png deleted file mode 100644 index 02251f4..0000000 Binary files a/RIT-EMS-main/frontend/src/assets/hero.png and /dev/null differ diff --git a/RIT-EMS-main/frontend/src/assets/images/college-logo.png b/RIT-EMS-main/frontend/src/assets/images/college-logo.png deleted file mode 100644 index 876b707..0000000 Binary files a/RIT-EMS-main/frontend/src/assets/images/college-logo.png and /dev/null differ diff --git a/RIT-EMS-main/frontend/src/assets/images/ritchennai.jpg b/RIT-EMS-main/frontend/src/assets/images/ritchennai.jpg deleted file mode 100644 index a374d21..0000000 Binary files a/RIT-EMS-main/frontend/src/assets/images/ritchennai.jpg and /dev/null differ diff --git a/RIT-EMS-main/frontend/src/assets/images/rsb_logo.png b/RIT-EMS-main/frontend/src/assets/images/rsb_logo.png deleted file mode 100644 index 715aa62..0000000 Binary files a/RIT-EMS-main/frontend/src/assets/images/rsb_logo.png and /dev/null differ diff --git a/RIT-EMS-main/frontend/src/assets/react.svg b/RIT-EMS-main/frontend/src/assets/react.svg deleted file mode 100644 index 6c87de9..0000000 --- a/RIT-EMS-main/frontend/src/assets/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/RIT-EMS-main/frontend/src/assets/vite.svg b/RIT-EMS-main/frontend/src/assets/vite.svg deleted file mode 100644 index 5101b67..0000000 --- a/RIT-EMS-main/frontend/src/assets/vite.svg +++ /dev/null @@ -1 +0,0 @@ -Vite diff --git a/RIT-EMS-main/frontend/src/components/DashboardLayout.tsx b/RIT-EMS-main/frontend/src/components/DashboardLayout.tsx deleted file mode 100644 index bae41d3..0000000 --- a/RIT-EMS-main/frontend/src/components/DashboardLayout.tsx +++ /dev/null @@ -1,214 +0,0 @@ -import { Sidebar } from './Sidebar'; -import { Search, Bell, Settings, LogOut, User as UserIcon, Plus, Calendar, ClipboardList, CheckCircle, Users, BookOpen, Zap, Clock, History as HistoryIcon, LayoutGrid, FileSpreadsheet } from 'lucide-react'; -import { useAuth } from '../context/AuthContext'; -import { useState, useEffect, useRef } from 'react'; -import { API_BASE_URL } from '../lib/config'; -import { cn } from '../lib/utils'; -import { motion, AnimatePresence } from 'framer-motion'; - -interface DashboardLayoutProps { - children: React.ReactNode; - activeItem: string; - onItemClick: (id: string) => void; -} - -export const DashboardLayout: React.FC = ({ - children, - activeItem, - onItemClick -}) => { - const { user, logout } = useAuth(); - const [searchQuery, setSearchQuery] = useState(''); - const [isSearchOpen, setIsSearchOpen] = useState(false); - const [events, setEvents] = useState([]); - const searchRef = useRef(null); - - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if (searchRef.current && !searchRef.current.contains(event.target as Node)) { - setIsSearchOpen(false); - } - }; - document.addEventListener('mousedown', handleClickOutside); - return () => document.removeEventListener('mousedown', handleClickOutside); - }, []); - - useEffect(() => { - if (isSearchOpen && events.length === 0) { - fetch(API_BASE_URL + '/api/events') - .then(res => res.json()) - .then(data => setEvents(Array.isArray(data) ? data : [])) - .catch(err => console.error('Search fetch failed:', err)); - } - }, [isSearchOpen]); - - const navItems = [ - { id: 'dashboard', label: 'Dashboard', icon: LayoutGrid, description: 'Main overview and stats' }, - { id: 'approvals', label: 'Approvals', icon: CheckCircle, description: 'Review pending requests', roles: ['HOD', 'PRINCIPAL', 'ADMIN'] }, - { id: 'events', label: 'All Events', icon: ClipboardList, description: 'Browse institution events' }, - { id: 'checklist', label: 'Checklist', icon: Calendar, description: 'Audit and compliance view' }, - { id: 'history', label: 'History', icon: HistoryIcon, description: 'Event ledger and audit trail' }, - { id: 'user-management', label: 'Manage Users', icon: Users, description: 'User roles and access', roles: ['ADMIN'] }, - { id: 'classes', label: 'Classes', icon: BookOpen, description: 'Academic structure', roles: ['ADMIN'] }, - { id: 'import-excel', label: 'Import Excel', icon: FileSpreadsheet, description: 'Bulk upload from response sheets', roles: ['ADMIN', 'PRINCIPAL'] }, - { id: 'automation', label: 'Automation', icon: Zap, description: 'Smart scheduling tools', roles: ['ADMIN', 'PRINCIPAL', 'HOD'] }, - ].filter(item => !item.roles || item.roles.includes(user?.role || '')); - - const filteredNav = searchQuery.length > 1 - ? navItems.filter(item => item.label.toLowerCase().includes(searchQuery.toLowerCase())) - : []; - - const filteredEvents = searchQuery.length > 1 - ? events.filter(e => - e.title.toLowerCase().includes(searchQuery.toLowerCase()) || - e.department?.toLowerCase().includes(searchQuery.toLowerCase()) - ).slice(0, 5) - : []; - - const handleResultClick = (id: string, type: 'nav' | 'event') => { - if (type === 'nav') { - onItemClick(id); - } else { - // For events, we'll navigate to 'events' and we could potentially filter there - onItemClick('events'); - } - setSearchQuery(''); - setIsSearchOpen(false); - }; - - return ( -
- -
- {/* Header */} -
-
- - { - setSearchQuery(e.target.value); - setIsSearchOpen(true); - }} - onFocus={() => setIsSearchOpen(true)} - placeholder="Search events, pages, or tools..." - className="w-full bg-white border border-slate-200/60 rounded-[1.25rem] py-3 pl-12 pr-4 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-brand-indigo/10 focus:border-brand-indigo transition-all shadow-sm" - /> - - - {isSearchOpen && (filteredNav.length > 0 || filteredEvents.length > 0) && ( - - {filteredNav.length > 0 && ( -
-

Navigation

- {filteredNav.map(item => ( - - ))} -
- )} - - {filteredEvents.length > 0 && ( -
-

Recent Events

- {filteredEvents.map(event => ( - - ))} -
- )} -
- )} -
-
- -
- - -
- -
- -
-
- -
-
- - {user?.fullName} - - - {user?.role} - -
-
- - -
-
- -
- {children} -
-
-
- ); -}; diff --git a/RIT-EMS-main/frontend/src/components/Sidebar.tsx b/RIT-EMS-main/frontend/src/components/Sidebar.tsx deleted file mode 100644 index 3d6473e..0000000 --- a/RIT-EMS-main/frontend/src/components/Sidebar.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import React, { useState } from 'react'; -import { - LayoutGrid, - ClipboardList, - CheckSquare, - History as HistoryIcon, - Zap, - BookOpen, - PlusCircle, - ChevronRight, - ShieldCheck, - Users, - Calendar, - HelpCircle, - ExternalLink, - CheckCircle, - Bell -} from 'lucide-react'; -import { cn } from '../lib/utils'; -import { motion } from 'framer-motion'; -import ritLogo from '../assets/images/college-logo.png'; -import { useAuth } from '../context/AuthContext'; - -interface SidebarProps { - activeItem: string; - onItemClick: (id: string) => void; -} - -export const Sidebar: React.FC = ({ activeItem, onItemClick }) => { - const { user } = useAuth(); - const isClubAuthorized = user?.isClubCoordinator || user?.role === 'ADMIN'; - - const menuItems = [ - { icon: LayoutGrid, label: 'Dashboard', id: 'dashboard' }, - ...((user?.role === 'HOD' || user?.role === 'PRINCIPAL') ? [{ icon: CheckCircle, label: 'Approvals', id: 'approvals' }] : []), - ...(isClubAuthorized ? [{ icon: ShieldCheck, label: 'Clubs', id: 'clubs' }] : []), - { icon: ClipboardList, label: 'All Events', id: 'events' }, - { icon: CheckSquare, label: 'Checklist', id: 'checklist' }, - { icon: HistoryIcon, label: 'History', id: 'history' }, - ...((user?.role === 'ADMIN' || user?.role === 'PRINCIPAL' || user?.role === 'HOD') ? [{ icon: Zap, label: 'Automation', id: 'automation' }] : []), - ...(user?.role === 'ADMIN' ? [{ icon: BookOpen, label: 'Classes', id: 'classes' }] : []), - ...(user?.role === 'ADMIN' ? [{ icon: Users, label: 'Manage Users', id: 'user-management' }] : []), - ...(user?.role === 'ADMIN' ? [{ icon: Bell, label: 'Manage Notices', id: 'manage-notices' }] : []), - ...((user?.role === 'FACULTY' || user?.role === 'HOD' || user?.role === 'ADMIN') ? [{ icon: Users, label: 'Student Hub', id: 'student-registrations' }] : []) - ]; - - return ( - - ); -}; diff --git a/RIT-EMS-main/frontend/src/components/dashboard/AllEvents.tsx b/RIT-EMS-main/frontend/src/components/dashboard/AllEvents.tsx deleted file mode 100644 index 718ddbf..0000000 --- a/RIT-EMS-main/frontend/src/components/dashboard/AllEvents.tsx +++ /dev/null @@ -1,234 +0,0 @@ -import { API_BASE_URL } from '../../lib/config'; -import React, { useEffect, useState } from 'react'; -import { motion } from 'framer-motion'; -import { - Calendar, - MapPin, - Building2, - Clock, - ChevronRight, - Filter, - Search, - MoreVertical, - FileSpreadsheet -} from 'lucide-react'; -import { cn } from '../../lib/utils'; -import { useAuth } from '../../context/AuthContext'; -import { StatusTimeline, type Event } from './EventStatusTimeline'; -import { Pagination } from './Pagination'; - -interface AllEventsProps { - onEditEvent?: (event: any) => void; -} - -export const AllEvents: React.FC = ({ onEditEvent }) => { - const { user } = useAuth(); - const [events, setEvents] = useState([]); - const [isLoading, setIsLoading] = useState(true); - const [searchTerm, setSearchTerm] = useState(''); - - useEffect(() => { - fetchEvents(); - }, []); - - const parseDate = (dateSource: any): Date | null => { - if (!dateSource) return null; - if (typeof dateSource === 'string') return new Date(dateSource); - if (Array.isArray(dateSource)) { - return new Date(dateSource[0], dateSource[1] - 1, dateSource[2], dateSource[3] || 0, dateSource[4] || 0); - } - return null; - }; - - const fetchEvents = async () => { - try { - const response = await fetch(API_BASE_URL + '/api/events'); - if (response.ok) { - const data = await response.json(); - setEvents(data); - } - } catch (error) { - console.error('Failed to fetch events:', error); - } finally { - setIsLoading(false); - } - }; - - const getStatusColor = (status: Event['status']) => { - switch (status) { - case 'REQUESTED': return 'bg-brand-glow text-brand-indigo border-brand-indigo/20'; - case 'PENDING_PR': return 'bg-amber-50 text-amber-600 border-amber-100'; - case 'APPROVED': return 'bg-emerald-50 text-emerald-600 border-emerald-100'; - case 'COMPLETED': return 'bg-slate-100 text-slate-600 border-slate-200'; - case 'CANCELLED': return 'bg-red-50 text-red-600 border-red-100'; - default: return 'bg-slate-50 text-slate-500 border-slate-100'; - } - }; - - - const [currentPage, setCurrentPage] = useState(1); - const [itemsPerPage, setItemsPerPage] = useState(10); - - const filteredEvents = events - .filter(event => - event.title.toLowerCase().includes(searchTerm.toLowerCase()) || - event.department.toLowerCase().includes(searchTerm.toLowerCase()) - ) - .sort((a, b) => { - const dateA = new Date(a.updatedAt || a.createdAt || 0).getTime(); - const dateB = new Date(b.updatedAt || b.createdAt || 0).getTime(); - return dateB - dateA; - }); - - const totalPages = Math.ceil(filteredEvents.length / itemsPerPage); - const startIndex = (currentPage - 1) * itemsPerPage; - const currentEvents = filteredEvents.slice(startIndex, startIndex + itemsPerPage); - - useEffect(() => { - setCurrentPage(1); - }, [searchTerm]); - - return ( -
- {/* Header & Controls */} -
-
-

All Events

-

Overview of all institutional activities and their status.

-
- -
-
- - setSearchTerm(e.target.value)} - className="bg-white border border-slate-200 rounded-xl py-2 pl-10 pr-4 text-sm focus:outline-none focus:ring-2 focus:ring-brand-indigo/10 focus:border-brand-indigo transition-all premium-shadow-sm" - /> -
- {(user?.role === 'ADMIN' || user?.role === 'PRINCIPAL') && ( - - )} - -
-
- - {/* Events List */} -
- {isLoading ? ( -
Loading events...
- ) : filteredEvents.length === 0 ? ( -
-
- -
-

No events found matching your search.

-
- ) : ( - <> -
- - - - - - - - - - - - {currentEvents.map((event, idx) => ( - - - - - - - - ))} - -
Event DetailsDate & VenueDepartmentStatusActions
-
- {event.title} - {event.type} • {event.institution} -
-
-
-
- - {parseDate(event.startDate) ? parseDate(event.startDate)!.toLocaleDateString('en-IN', { day: '2-digit', month: 'short', year: 'numeric' }) : 'N/A'} -
-
- - {event.location} -
-
-
-
-
- {event.department.substring(0, 2)} -
- {event.department} -
-
- {user?.role === 'FACULTY' && event.proposer?.email === user?.email ? ( - - ) : ( - - {event.status === 'PENDING_PR' ? 'PENDING PRINCIPAL' : event.status} - - )} - -
- {(user?.role === 'ADMIN' || (event.status === 'REQUESTED' && event.proposer?.email === user?.email)) && onEditEvent && ( - - )} - -
-
-
- - { - setItemsPerPage(val); - setCurrentPage(1); - }} - itemsPerPageOptions={[5, 10, 20, 50]} - /> - - )} -
-
- ); -}; diff --git a/RIT-EMS-main/frontend/src/components/dashboard/ApprovalsView.tsx b/RIT-EMS-main/frontend/src/components/dashboard/ApprovalsView.tsx deleted file mode 100644 index 5d2ecb9..0000000 --- a/RIT-EMS-main/frontend/src/components/dashboard/ApprovalsView.tsx +++ /dev/null @@ -1,418 +0,0 @@ -import { API_BASE_URL } from '../../lib/config'; -import React, { useEffect, useState, useMemo } from 'react'; -import { motion, AnimatePresence } from 'framer-motion'; -import { - CheckCircle, - XCircle, - Clock, - User, - Building2, - ChevronRight, - AlertCircle, - ShieldCheck, - MapPin, - Wallet, - Users, - Layers, - Ticket, - AlertTriangle, - FileText, - Heart, - Calendar -} from 'lucide-react'; -import { useAuth } from '../../context/AuthContext'; -import { cn } from '../../lib/utils'; -import { Pagination } from './Pagination'; - -interface Event { - id: number; - title: string; - startDate: string; - endDate: string; - type: string; - institution: string; - department: string; - academicYears: string[]; - status: string; - location: string; - proposer?: { - fullName: string; - department: string; - }; - budget: number; - hasRegistrationFee: boolean; - registrationFee: number; - category: string; - targetedSections: string[]; - conflictMessage?: string; - description?: string; - sponsors?: string[]; - rejectionReason?: string; -} - -export const ApprovalsView: React.FC = () => { - const { user } = useAuth(); - const [events, setEvents] = useState([]); - const [isLoading, setIsLoading] = useState(true); - const [processingId, setProcessingId] = useState(null); - const [selectedEvent, setSelectedEvent] = useState(null); - const [currentPage, setCurrentPage] = useState(1); - const [itemsPerPage, setItemsPerPage] = useState(5); - - useEffect(() => { - fetchEvents(); - }, []); - - const fetchEvents = async () => { - try { - const response = await fetch(API_BASE_URL + '/api/events'); - if (response.ok) { - const data = await response.json(); - // Filter based on role - if (user?.role === 'HOD') { - const userDepts = user.department ? user.department.split(',').map(d => d.trim().toLowerCase()) : []; - setEvents(data.filter((e: Event) => e.status === 'REQUESTED' && userDepts.includes(e.department?.trim().toLowerCase()))); - } else if (user?.role === 'PRINCIPAL') { - setEvents(data.filter((e: Event) => e.status === 'PENDING_PR')); - } - } - } catch (error) { - console.error('Failed to fetch events:', error); - } finally { - setIsLoading(false); - } - }; - - const handleAction = async (id: number, action: 'approve' | 'reject') => { - let reason = ''; - if (action === 'reject') { - reason = window.prompt('Please enter a rejection reason:') || ''; - if (!reason) return; - } - - setProcessingId(id); - try { - const response = await fetch(`${API_BASE_URL}/api/events/${id}/${action}?userId=${user?.id}`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: action === 'reject' ? JSON.stringify({ reason }) : undefined - }); - - if (response.ok) { - setEvents(events.filter(e => e.id !== id)); - setSelectedEvent(null); - } else { - const err = await response.json(); - alert(err.message || 'Operation failed'); - } - } catch (error) { - console.error(`Failed to ${action} event:`, error); - } finally { - setProcessingId(null); - } - }; - - const sortedEvents = useMemo(() => { - return [...events].sort((a: any, b: any) => { - const dateA = new Date(a.updatedAt || a.createdAt || 0).getTime(); - const dateB = new Date(b.updatedAt || b.createdAt || 0).getTime(); - return dateB - dateA; - }); - }, [events]); - - const currentEvents = sortedEvents.slice( - (currentPage - 1) * itemsPerPage, - currentPage * itemsPerPage - ); - - return ( -
-
-

Pending Approvals

-

Review and take action on event proposals from your {user?.role === 'HOD' ? 'department' : 'institution'}.

-
- -
- {isLoading ? ( -
-
-
- ) : events.length === 0 ? ( -
- -

Queue is Empty

-

All proposals have been processed. Great work!

-
- ) : ( - - {currentEvents.map((event) => ( - setSelectedEvent(event)} - className={cn( - "bg-white rounded-[2rem] p-6 border transition-all flex flex-col md:flex-row items-center justify-between gap-6 cursor-pointer group", - event.conflictMessage ? "border-red-200 bg-red-50/30" : "border-slate-100 hover:premium-shadow" - )} - > -
-
- {event.title[0]} -
-
-
- {event.category === 'CLUB' && ( - - Institutional Club - - )} - - {event.type} - -
-

{event.title}

- - {event.conflictMessage ? ( -
- - {event.conflictMessage} -
- ) : ( -
-
- - {event.proposer?.fullName || 'Faculty Member'} -
-
- - {new Date(event.startDate).toLocaleDateString()} -
-
- )} -
-
- -
e.stopPropagation()}> - - -
-
- ))} -
- )} -
- - {events.length > 0 && ( - { - setItemsPerPage(val); - setCurrentPage(1); - }} - itemsPerPageOptions={[5, 10, 15, 20]} - /> - )} - - {/* Detail Modal */} - - {selectedEvent && ( -
- setSelectedEvent(null)} - className="absolute inset-0 bg-slate-900/40 backdrop-blur-sm" - /> - -
-
-
- Proposal Details - - {selectedEvent.institution} - {selectedEvent.category === 'CLUB' && ( - <> - - Institutional Club Event - - )} -
-

{selectedEvent.title}

-
- -
- -
- {/* Description Section */} - {selectedEvent.description && ( -
-
- - Event Description -
-

- {selectedEvent.description} -

-
- )} - -
-
-
-
- - Schedule -
-

- {new Date(selectedEvent.startDate).toLocaleString()} -

-
-
-
- - Venue -
-

{selectedEvent.location}

-
-
- -
-
-
- - Proposed By -
-

{selectedEvent.proposer?.fullName || 'Faculty'}

-

{selectedEvent.department}

-
-
-
- - Target Audience -
-

{selectedEvent.academicYears.join(', ')} Batches

-
-
-
- - {/* Sponsors Section */} - {selectedEvent.sponsors && selectedEvent.sponsors.length > 0 && ( -
-
- - Event Sponsors -
-
- {selectedEvent.sponsors.map((sponsor, idx) => ( - - {sponsor} - - ))} -
-
- )} - -
-
-
- - Estimated Budget -
-

₹{selectedEvent.budget?.toLocaleString() || '0'}

-
-
-
- - Registration -
-

- {selectedEvent.hasRegistrationFee ? `₹${selectedEvent.registrationFee}` : 'FREE'} -

-
-
- - {selectedEvent.conflictMessage && ( -
- -
-

Critical Conflict Detected

-

{selectedEvent.conflictMessage}

-
-
- )} - -
- - -
-
-
-
- )} -
-
- ); -}; diff --git a/RIT-EMS-main/frontend/src/components/dashboard/AutomationView.tsx b/RIT-EMS-main/frontend/src/components/dashboard/AutomationView.tsx deleted file mode 100644 index 4328270..0000000 --- a/RIT-EMS-main/frontend/src/components/dashboard/AutomationView.tsx +++ /dev/null @@ -1,787 +0,0 @@ -import { API_BASE_URL } from '../../lib/config'; -import React, { useState, useEffect } from 'react'; -import { - Zap, - ArrowRightLeft, - ChevronLeft, - ChevronRight, - ShieldAlert, - Play, - Building2, - Users, - Layers, - Calendar, - ChevronDown, - Loader2, - CheckCircle2, - X, - AlertTriangle, - Clock, - ChevronUp -} from 'lucide-react'; -import { motion, AnimatePresence } from 'framer-motion'; -import { cn } from '../../lib/utils'; -import { - format, - addMonths, - subMonths, - startOfMonth, - endOfMonth, - startOfWeek, - endOfWeek, - eachDayOfInterval, - isSameMonth, - isSameDay -} from 'date-fns'; - -const DEPARTMENTS = [ - "AI&DS", "AI&ML", "CSE", "CCE", "CSBS", "ECE", - "MECH", "EE(VLSI)", "BIOTECH", "Placement Department", - "H&S Dept", "Club", "Centre" -]; - -const BATCHES = ['1st Year', '2nd Year', '3rd Year', '4th Year']; - -const parseDate = (dateSource: any): Date | null => { - if (!dateSource) return null; - if (typeof dateSource === 'string') return new Date(dateSource); - if (Array.isArray(dateSource)) { - return new Date(dateSource[0], dateSource[1] - 1, dateSource[2], dateSource[3] || 0, dateSource[4] || 0); - } - return null; -}; - -interface Event { - id: number; - title: string; - startDate: string; - endDate: string; - department: string; - academicYears: string[]; - institution?: string; - type?: string; - category?: string; - location?: string; - proposer?: any; -} - -const MiniCalendar: React.FC<{ - title: string; - subtitle: string; - date: Date; - onDateChange: (d: Date) => void; - events: Event[]; - accentColor: string; - onEventClick?: (e: Event) => void; -}> = ({ title, subtitle, date, onDateChange, events, accentColor, onEventClick }) => { - const days = eachDayOfInterval({ - start: startOfWeek(startOfMonth(date)), - end: endOfWeek(endOfMonth(date)) - }); - - return ( -
-
-
-

{title}

-

{subtitle}

-
-
- - -
-
-
-
- {format(date, 'MMMM yyyy')} -
-
- {['S', 'M', 'T', 'W', 'T', 'F', 'S'].map((d, i) => ( -
{d}
- ))} - {days.map(day => { - const isCurrentMonth = isSameMonth(day, date); - const dayStr = format(day, 'yyyy-MM-dd'); - const dayEvents = events.filter(e => { - const d = parseDate(e.startDate); - return d && format(d, 'yyyy-MM-dd') === dayStr; - }); - - return ( -
- {format(day, 'd')} -
- {dayEvents.map(e => ( -
onEventClick?.(e)} - className="bg-brand-glow border border-brand-indigo/10 rounded-lg p-2 transition-all hover:scale-[1.02] cursor-pointer" - > -
{e.title}
-

{e.department}

-
- ))} -
-
- ); - })} -
-
-
- ); -}; - -export const AutomationView: React.FC = () => { - const [sourceDate, setSourceDate] = useState(new Date()); - const [targetDate, setTargetDate] = useState(addMonths(new Date(), 6)); - const [events, setEvents] = useState([]); - const [isLoading, setIsLoading] = useState(true); - const [isExecuting, setIsExecuting] = useState(false); - const [status, setStatus] = useState<'idle' | 'success'>('idle'); - - const [sourceConfig, setSourceConfig] = useState({ - institution: 'RIT', - department: 'AI&DS', - batch: '1st Year' - }); - - const [targetConfig, setTargetConfig] = useState({ - institution: 'RIT', - department: 'AI&DS', - batch: '1st Year' - }); - - useEffect(() => { - fetchEvents(); - }, []); - - const fetchEvents = async () => { - try { - const response = await fetch(API_BASE_URL + '/api/events'); - if (response.ok) { - const data = await response.json(); - setEvents(data); - } - } catch (error) { - console.error('Failed to fetch events:', error); - } finally { - setIsLoading(false); - } - } - - const filteredSourceEvents = events.filter(e => - e.department?.trim() === sourceConfig.department.trim() && - (e.academicYears || []).map((y: string) => y.trim()).includes(sourceConfig.batch.trim()) - ); - - const filteredTargetEvents = events.filter(e => - e.department?.trim() === targetConfig.department.trim() && - (e.academicYears || []).map((y: string) => y.trim()).includes(targetConfig.batch.trim()) - ); - - const [proposedChanges, setProposedChanges] = useState([]); - const [showReviewModal, setShowReviewModal] = useState(false); - const [selectedEvent, setSelectedEvent] = useState(null); - - const prepareSwap = () => { - const changes = filteredSourceEvents.map(event => { - const originalDate = parseDate(event.startDate); - if (!originalDate) return { ...event, resolution: 'skip' }; - - const isOddSem = originalDate.getMonth() >= 6; - const targetBaseDate = isOddSem ? subMonths(originalDate, 6) : addMonths(originalDate, 6); - - // Preserving time - const targetDateStr = format(targetBaseDate, 'yyyy-MM-dd'); - const timeStr = format(originalDate, 'HH:mm:ss'); - const finalDateTimeStr = `${targetDateStr}T${timeStr}`; - - const dayOfWeek = targetBaseDate.getDay(); - const isWeekend = dayOfWeek === 0 || dayOfWeek === 6; - - // Conflict Detection (Any event on target date) - const targetConflicts = filteredTargetEvents.filter(te => - format(parseDate(te.startDate)!, 'yyyy-MM-dd') === targetDateStr - ); - - const hasTimeConflict = targetConflicts.some(tc => { - const tcDate = parseDate(tc.startDate); - return tcDate && format(tcDate, 'HH:mm') === format(originalDate, 'HH:mm'); - }); - - const isAlreadySwapped = targetConflicts.some(tc => - tc.title.trim().toLowerCase() === event.title.trim().toLowerCase() - ); - - return { - ...event, - originalDate: event.startDate, - targetDate: finalDateTimeStr, // Now includes time - targetDepartment: targetConfig.department, - targetBatch: targetConfig.batch, - isWeekend, - isAlreadySwapped, - targetConflicts, - hasTimeConflict, - resolution: isAlreadySwapped ? 'skip' : (targetConflicts.length > 0 ? 'review' : 'create'), - adjustment: isWeekend ? 'monday' : 'none' - }; - }); - setProposedChanges(changes); - setShowReviewModal(true); - }; - - const handleExecuteSwap = async () => { - setIsExecuting(true); - - const finalizedChanges = proposedChanges - .filter(c => c.resolution !== 'skip') - .map(change => { - let finalDate = new Date(change.targetDate); - - // Handle Weekend Adjustments - if (change.resolution !== 'reschedule' && change.isWeekend) { - if (change.adjustment === 'friday') { - const day = finalDate.getDay(); - const diff = day === 6 ? 1 : 2; - finalDate.setDate(finalDate.getDate() - diff); - } else if (change.adjustment === 'monday') { - const day = finalDate.getDay(); - const diff = day === 6 ? 2 : 1; - finalDate.setDate(finalDate.getDate() + diff); - } - } - - return { - ...change, - finalDate: format(finalDate, "yyyy-MM-dd'T'HH:mm:ss") - }; - }); - - console.log('Finalized Swap Payload:', finalizedChanges); - - try { - const response = await fetch(API_BASE_URL + '/api/events/batch-create', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(finalizedChanges.map(c => ({ - ...c, - targetDepartment: c.targetDepartment, - targetBatch: c.targetBatch, - startDate: c.finalDate - }))) - }); - - if (response.ok) { - setStatus('success'); - fetchEvents(); - } else { - const errData = await response.json(); - alert('Failed to execute automation swap: ' + (errData.message || 'Unknown error')); - } - } catch (error) { - console.error('Automation swap failed:', error); - alert('Network error during automation swap'); - } finally { - setIsExecuting(false); - setShowReviewModal(false); - setTimeout(() => setStatus('idle'), 3000); - } - }; - - return ( -
-
-
-

Event Automation

-

Configure and manage automated department event workflows.

-
-
- -
-
- -
-
-
-
- -
-
-

Source Selection

-

Select branch to clone events from

-
-
-
-
- -
- RIT - -
-
-
- - -
-
- - -
-
-
- -
-
-
- -
-
-

Target Workspace

-

Automation output destination

-
-
-
-
- -
- RIT - -
-
-
- - -
-
- - -
-
-
-
- -
-
-
- -
-
-

Automation Safety Protocols Active

-

Cloning institutional events shifts schedules by +/- 6 months (Semester Swap).

-
-
-
- - -
-
- -
- - -
- - - {selectedEvent && ( -
- setSelectedEvent(null)} - className="absolute inset-0 bg-slate-900/40 backdrop-blur-sm" - /> - -
-
- - {selectedEvent.category || 'Academic'} Event - -

{selectedEvent.title}

-
- -
- -
-
-
- Start Date -

- {parseDate(selectedEvent.startDate) ? format(parseDate(selectedEvent.startDate)!, 'PPP') : 'N/A'} -

-
-
- Venue -

{selectedEvent.location || 'Seminar Hall'}

-
-
- Department -

{selectedEvent.department}

-
-
- Academic Year -

{selectedEvent.academicYears?.join(', ') || 'N/A'}

-
-
- -
- Proposer Information -
-
- {selectedEvent.proposer?.fullName?.charAt(0) || 'F'} -
-
-

{selectedEvent.proposer?.fullName || 'Faculty Member'}

-

{selectedEvent.proposer?.email || 'faculty@rit.edu'}

-
-
-
-
- -
- -
-
-
- )} -
- - - {showReviewModal && ( -
- setShowReviewModal(false)} - className="absolute inset-0 bg-slate-900/40 backdrop-blur-sm" - /> - -
-
-

Review Automated Changes

-

Audit and adjust planned semester-swap dates.

-
- -
- -
-
- {proposedChanges.map((change, idx) => ( -
0 ? "bg-red-50/30 border-red-100" : - change.isWeekend ? "bg-amber-50 border-amber-100" : "bg-white border-slate-100" - )}> -
-
-
- Event -

{change.title}

-
-
-
- - - {parseDate(change.originalDate) ? format(parseDate(change.originalDate)!, 'MMM d') : 'N/A'} - - - - {parseDate(change.targetDate) ? format(parseDate(change.targetDate)!, 'MMM d, yyyy') : 'N/A'} - -
- - {change.isAlreadySwapped && ( - - Already Swapped - - )} -
-
- -
- {change.targetConflicts?.length > 0 && change.resolution !== 'skip' && ( -
- -
- Conflict Detected - - {change.targetConflicts.length} event(s) already on this date - {change.hasTimeConflict && " (Time Overlap!)"} - -
-
- )} - -
- - - -
- - {/* Weekend Quick-Shift */} - {change.isWeekend && change.resolution !== 'skip' && change.resolution !== 'reschedule' && ( -
- - -
- )} -
-
- - {/* Expanded Conflict / Reschedule Details */} - {(change.resolution === 'reschedule' || (change.targetConflicts?.length > 0 && change.resolution !== 'skip')) && ( - - {change.targetConflicts?.length > 0 && ( -
- Conflicts at Destination - {change.targetConflicts.map((conf: any) => ( -
-
-
- {conf.department.substring(0, 2)} -
- {conf.title} -
-
- - {format(new Date(conf.startDate), 'hh:mm a')} -
-
- ))} -
- )} - - {change.resolution === 'reschedule' && ( -
-
- - { - const updated = [...proposedChanges]; - updated[idx].targetDate = e.target.value; - setProposedChanges(updated); - }} - className="w-full bg-white border border-amber-200 rounded-xl p-3 text-xs font-bold text-text-dark focus:outline-none focus:ring-2 focus:ring-amber-500/20" - /> -
-
- - -
-
- Shift Result - {format(new Date(change.targetDate), 'EEEE')} -
-
- )} -
- )} -
- ))} -
-
- -
- - -
-
-
- )} -
-
- ); -}; diff --git a/RIT-EMS-main/frontend/src/components/dashboard/ClassManagement.tsx b/RIT-EMS-main/frontend/src/components/dashboard/ClassManagement.tsx deleted file mode 100644 index afd69d2..0000000 --- a/RIT-EMS-main/frontend/src/components/dashboard/ClassManagement.tsx +++ /dev/null @@ -1,643 +0,0 @@ -import { API_BASE_URL } from '../../lib/config'; -import React, { useState, useEffect } from 'react'; -import { motion, AnimatePresence } from 'framer-motion'; -import { - Plus, - Search, - Trash2, - Layers, - RefreshCw, - AlertTriangle, - Building2, - GraduationCap, - ChevronRight, - X, - CheckCircle2 -} from 'lucide-react'; -import { cn } from '../../lib/utils'; -import { Pagination } from './Pagination'; -import { useDialog } from '../../context/DialogContext'; - -interface ClassMapping { - id: number; - institution: string; - department: string; - academicYear: string; - sections: string[]; - status: string; -} - -const ritDepartments = ['AI&DS', 'AI&ML', 'CSE', 'CCE', 'CSBS', 'ECE', 'MECH', 'EE(VLSI)', 'BIOTECH', 'Placement Department', 'H&S Dept', 'Club', 'Centre']; -const rsbDepartments = ['PGDM']; -const years = ['1st Year', '2nd Year', '3rd Year', '4th Year']; - -import rsbLogo from '../../assets/images/rsb_logo.png'; -import ritLogo from '../../assets/images/college-logo.png'; - -export const ClassManagement: React.FC = () => { - const { showAlert, showConfirm } = useDialog(); - const [classes, setClasses] = useState([]); - const [isLoading, setIsLoading] = useState(true); - const [searchTerm, setSearchTerm] = useState(''); - const [newSection, setNewSection] = useState(''); - const [currentPage, setCurrentPage] = useState(1); - const [itemsPerPage, setItemsPerPage] = useState(10); - - const [formData, setFormData] = useState({ - institution: 'RIT', - department: 'AI&DS', - academicYear: '1st Year', - sections: [] as string[] - }); - - const [batches, setBatches] = useState([]); - const [newBatchName, setNewBatchName] = useState(''); - const [selectedBatchDept, setSelectedBatchDept] = useState('AI&DS'); - const [tempBatches, setTempBatches] = useState([]); - - useEffect(() => { - const deptBatches = batches.filter(b => b.department === selectedBatchDept); - setTempBatches(JSON.parse(JSON.stringify(deptBatches))); - }, [batches, selectedBatchDept]); - - const currentDepartments = formData.institution === 'RIT' ? ritDepartments : rsbDepartments; - - useEffect(() => { - if (formData.institution === 'RSB' && formData.department !== 'PGDM') { - setFormData(prev => ({ ...prev, department: 'PGDM', sections: [] })); - } - }, [formData.institution]); - - useEffect(() => { - fetchClasses(); - fetchBatches(); - }, []); - - const fetchBatches = async () => { - try { - const response = await fetch(API_BASE_URL + '/api/batches'); - if (response.ok) { - const data = await response.json(); - setBatches(data); - } - } catch (error) { - console.error('Failed to fetch batches:', error); - } - }; - - const fetchClasses = async () => { - try { - const response = await fetch(API_BASE_URL + '/api/classes'); - if (response.ok) { - const data = await response.json(); - setClasses(data); - } - } catch (error) { - console.error('Failed to fetch classes:', error); - } finally { - setIsLoading(false); - } - }; - - const handleAddSection = (e: React.FormEvent) => { - e.preventDefault(); - if (newSection && !formData.sections.includes(newSection.toUpperCase())) { - setFormData({ - ...formData, - sections: [...formData.sections, newSection.toUpperCase()] - }); - setNewSection(''); - } - }; - - const removeSection = (section: string) => { - setFormData({ - ...formData, - sections: formData.sections.filter(s => s !== section) - }); - }; - - const handleSave = async () => { - if (formData.sections.length === 0) { - showAlert('Required', 'Please add at least one section', 'error'); - return; - } - - try { - const response = await fetch(API_BASE_URL + '/api/classes', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(formData) - }); - - if (response.ok) { - fetchClasses(); - setFormData({ ...formData, sections: [] }); - showAlert('Success', 'Class mapping saved successfully.', 'success'); - } - } catch (error) { - console.error('Failed to save class mapping:', error); - showAlert('Error', 'Failed to save class mapping.', 'error'); - } - }; - - const handleDelete = async (id: number) => { - showConfirm( - 'Delete Mapping', - 'Are you sure you want to delete this mapping?', - async () => { - try { - const response = await fetch(`${API_BASE_URL}/api/classes/${id}`, { - method: 'DELETE' - }); - if (response.ok) { - setClasses(prev => prev.filter(c => c.id !== id)); - showAlert('Success', 'Mapping deleted successfully.', 'success'); - } - } catch (error) { - console.error('Delete failed:', error); - showAlert('Error', 'Failed to delete mapping.', 'error'); - } - } - ); - }; - - const handlePromote = async () => { - showConfirm( - 'Academic Promotion', - `WARNING: This action will shift all academic structures for ${formData.institution} forward:\n• 1st Year → 2nd Year\n• 2nd Year → 3rd Year\n• 3rd Year → 4th Year\n• 4th Year mappings will be PERMANENTLY DELETED.\n\nDo you wish to proceed?`, - async () => { - try { - const response = await fetch(`${API_BASE_URL}/api/classes/promote?institution=${formData.institution}`, { - method: 'POST' - }); - if (response.ok) { - fetchClasses(); - showAlert('Success', `${formData.institution} academic year promotion completed successfully!`, 'success'); - } - } catch (error) { - console.error('Promotion failed:', error); - showAlert('Error', 'Promotion failed.', 'error'); - } - } - ); - }; - - const handleCreateTempBatch = () => { - if (!newBatchName.trim()) { - showAlert('Required', 'Please enter a batch name', 'error'); - return; - } - const newBatch = { - id: Date.now() + Math.floor(Math.random() * 1000), - name: newBatchName.trim(), - department: selectedBatchDept, - classes: [] - }; - setTempBatches([...tempBatches, newBatch]); - setNewBatchName(''); - }; - - const handleDeleteTempBatch = (batchId: number) => { - setTempBatches(tempBatches.filter(b => b.id !== batchId)); - }; - - const handleToggleClassInTempBatch = (batchId: number, classStr: string) => { - setTempBatches(tempBatches.map(b => { - if (b.id !== batchId) return b; - const isAssigned = b.classes?.includes(classStr); - return { - ...b, - classes: isAssigned - ? b.classes.filter((c: string) => c !== classStr) - : [...(b.classes || []), classStr] - }; - })); - }; - - const handleSaveChanges = async () => { - try { - const originalDeptBatches = batches.filter(b => b.department === selectedBatchDept); - - // 1. Identify deleted batches (in original but not in temp) - const deletedBatches = originalDeptBatches.filter(ob => !tempBatches.some(tb => String(tb.id) === String(ob.id))); - - // 2. Perform deletes - for (const db of deletedBatches) { - await fetch(`${API_BASE_URL}/api/batches/${db.id}`, { method: 'DELETE' }); - } - - // 3. Save / Update current batches in tempBatches - for (const tb of tempBatches) { - await fetch(API_BASE_URL + '/api/batches', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - id: tb.id, - name: tb.name, - department: tb.department, - classes: tb.classes - }) - }); - } - - // 4. Refresh state - await fetchBatches(); - showAlert('Success', 'Batch configurations saved successfully.', 'success'); - } catch (error) { - console.error('Failed to save batch changes:', error); - showAlert('Error', 'Failed to save changes.', 'error'); - } - }; - - const filteredClasses = classes - .filter(c => - c.institution === formData.institution && ( - c.department.toLowerCase().includes(searchTerm.toLowerCase()) || - c.academicYear.toLowerCase().includes(searchTerm.toLowerCase()) - ) - ) - .sort((a, b) => b.id - a.id); - - const currentClasses = filteredClasses.slice( - (currentPage - 1) * itemsPerPage, - currentPage * itemsPerPage - ); - - const selectedDeptClasses = classes.filter(c => c.institution === formData.institution && c.department === formData.department); - const totalClassesCount = selectedDeptClasses.reduce((sum, c) => sum + c.sections.length, 0); - const hasMoreThanFourClasses = totalClassesCount > 4; - const deptClassesList = selectedDeptClasses.flatMap(c => c.sections.map(sec => `${c.academicYear} - ${sec}`)); - - const selectedBatchDeptClasses = classes.filter(c => c.department === selectedBatchDept); - const batchDeptClassesList = selectedBatchDeptClasses.flatMap(c => c.sections.map(sec => `${c.academicYear} - ${sec}`)); - - return ( -
- {/* Header */} -
-
-

Class Management

-

Define institutional academic structures & sections

-
- -
- -
- -
-
-
- -
- {/* Left Column - Form */} -
- -
-
- -
-

Add New Mapping

-
- -
- {/* Institution */} -
- -
- {[ - { id: 'RIT', logo: ritLogo, label: 'RIT' }, - { id: 'RSB', logo: rsbLogo, label: 'RSB' } - ].map(inst => ( - - ))} -
-
- - {/* Department */} -
- - -
- - {/* Academic Year */} -
- - -
- - {/* Sections */} -
- -
-
- - {formData.sections.map(section => ( - - {section} - - - ))} - -
-
- setNewSection(e.target.value)} - className="flex-1 bg-transparent border-none text-xs font-bold focus:ring-0 p-0" - /> - -
-
-
- - -
-
-
- - {/* Right Column - Table */} -
- -
-
-
-

Academic Structure

-
- -
- - setSearchTerm(e.target.value)} - className="w-full bg-slate-50 border-transparent rounded-2xl py-3 pl-12 pr-4 text-sm font-bold focus:bg-white focus:border-brand-indigo transition-all" - /> -
-
- -
- - - - - - - - - - - {isLoading ? ( - - ) : filteredClasses.length === 0 ? ( - - ) : ( - currentClasses.map((item, idx) => ( - - - - - - - )) - )} - -
InstitutionDepartment \ YearConfigured SectionsActions
Loading structure...
No academic structures defined.
-
- {item.institution} -
-
-
-
- {item.department.substring(0, 3)} -
-
-
-

{item.department}

-
- - {item.academicYear} -
-
-
-
-
- {item.sections.map(section => ( - - {section} - - ))} -
- - Ready -
-
-
-
- - -
-
-
- - { - setItemsPerPage(val); - setCurrentPage(1); - }} - itemsPerPageOptions={[5, 10, 20, 50]} - /> - -
-
- - {/* Batches Section - Always Visible */} -
-
-
-
- -
-
-

Department Batches

-

Configure custom student batches for auditing & event planning.

-
-
- -
- {/* Select Department */} -
- Department: - -
- - {/* Create Batch Form */} -
- setNewBatchName(e.target.value)} - className="bg-slate-50 border border-slate-200 rounded-xl py-2 px-4 text-xs font-bold focus:bg-white focus:border-brand-indigo outline-none transition-all text-slate-800" - /> - -
-
-
- -
- {tempBatches.map(batch => ( -
-
- {batch.name} - -
- -
- Assign Classes to this Batch: - {batchDeptClassesList.length > 0 ? ( -
- {batchDeptClassesList.map(cls => { - const isChecked = batch.classes?.includes(cls); - return ( - - ); - })} -
- ) : ( - No classes configured for {selectedBatchDept}. - )} -
-
- ))} - {tempBatches.length === 0 && ( -
- No batches created yet for {selectedBatchDept}. Use the form above to add your first batch. -
- )} -
- - {tempBatches.length > 0 && ( -
- -
- )} -
-
- ); -}; diff --git a/RIT-EMS-main/frontend/src/components/dashboard/ClubInstitutionalChecklist.tsx b/RIT-EMS-main/frontend/src/components/dashboard/ClubInstitutionalChecklist.tsx deleted file mode 100644 index dc74336..0000000 --- a/RIT-EMS-main/frontend/src/components/dashboard/ClubInstitutionalChecklist.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { motion } from 'framer-motion'; -import { Calendar, CheckCircle2, Circle } from 'lucide-react'; -import { cn } from '../../lib/utils'; -import { INSTITUTIONAL_EVENTS } from '../../constants/institutionalEvents'; -import { getCurrentAcademicYear } from '../../lib/dateUtils'; -import { API_BASE_URL } from '../../lib/config'; - -interface ClubEvent { - id: string; - name: string; - month: string; - semester: 'ODD' | 'EVEN'; -} - -interface Event { - id: number; - title: string; - status: string; - academicYears: string[]; -} - -interface ClubInstitutionalChecklistProps { - onEventClick: (data: { eventName: string, isClubEvent: boolean }) => void; -} - -export const ClubInstitutionalChecklist: React.FC = ({ onEventClick }) => { - const [events, setEvents] = useState([]); - const currentAcademicYear = getCurrentAcademicYear(); - - useEffect(() => { - fetch(API_BASE_URL + '/api/events') - .then(res => res.json()) - .then(data => setEvents(data)) - .catch(err => console.error('Failed to fetch events:', err)); - }, []); - - const getEventStatus = (eventName: string) => { - const matching = events.filter(e => - e.title.toLowerCase() === eventName.toLowerCase() && - e.academicYears?.includes(currentAcademicYear) && - (e.status?.toUpperCase() === 'APPROVED' || e.status?.toUpperCase() === 'COMPLETED') - ); - return matching.length > 0; - }; - - const oddSemesterEvents = INSTITUTIONAL_EVENTS.filter(e => e.semester === 'ODD'); - const evenSemesterEvents = INSTITUTIONAL_EVENTS.filter(e => e.semester === 'EVEN'); - - const SemesterCard = ({ title, subtitle, events, gradient }: { title: string, subtitle: string, events: ClubEvent[], gradient: string }) => ( -
-
-
-

{title}

-

{subtitle}

-
- -
- -
- {events.map((event, i) => { - const isScheduled = getEventStatus(event.name); - return ( - onEventClick({ eventName: event.name, isClubEvent: true })} - className="w-full flex items-center gap-6 group text-left" - > -
- -
- {isScheduled ? ( - - ) : ( -
- )} -
-
-
-

{event.name}

-

- {isScheduled ? 'Scheduled & Approved' : `Target: ${event.month}`} -

-
- - ); - })} -
-
- ); - - return ( -
-
-
-
-

Institutional Checklists

-

Track Institutional Club Requirements

-
-
- -
- - -
-
- ); -}; diff --git a/RIT-EMS-main/frontend/src/components/dashboard/EventDetailsModal.tsx b/RIT-EMS-main/frontend/src/components/dashboard/EventDetailsModal.tsx deleted file mode 100644 index c69fc33..0000000 --- a/RIT-EMS-main/frontend/src/components/dashboard/EventDetailsModal.tsx +++ /dev/null @@ -1,196 +0,0 @@ -import React from 'react'; -import { motion, AnimatePresence } from 'framer-motion'; -import { - X, - Calendar as CalendarIcon, - MapPin, - Clock, - Building2, - Users, - Tag, - Target -} from 'lucide-react'; -import { cn } from '../../lib/utils'; -import { format } from 'date-fns'; - -interface EventDetailsModalProps { - isOpen: boolean; - onClose: () => void; - event: any; -} - -export const EventDetailsModal: React.FC = ({ isOpen, onClose, event }) => { - if (!isOpen || !event) return null; - - const parseDate = (dateSource: any): Date | null => { - if (!dateSource) return null; - if (typeof dateSource === 'string') return new Date(dateSource); - if (Array.isArray(dateSource)) { - return new Date(dateSource[0], dateSource[1] - 1, dateSource[2], dateSource[3] || 0, dateSource[4] || 0); - } - return null; - }; - - const startDate = parseDate(event.startDate); - const endDate = parseDate(event.endDate); - - return ( - -
- - - - {/* Header */} -
-
-
- - {event.department} - - - {event.type} - -
-

- {event.title} -

-
- - - - {/* Background Decoration */} -
-
- - {/* Content */} -
-
-
-
- -
-
-

Date & Time

-

- {startDate ? format(startDate, 'MMMM d, yyyy') : 'TBD'} -

-

- {startDate ? format(startDate, 'hh:mm a') : 'TBD'} - {endDate ? format(endDate, 'hh:mm a') : 'TBD'} -

-
-
- -
-
- -
-
-

Venue

-

- {event.location || 'TBD'} -

-

- {event.institution || 'RIT'} -

-
-
-
- - {event.description && ( -
-

Event Description

-
-

- {event.description} -

-
-
- )} - -
- {event.academicYears && event.academicYears.length > 0 && ( -
-

- - Target Audience -

-
- {(event as any).targetedBatch ? ( - - {(event as any).targetedBatch} - - ) : ( - event.academicYears.map((year: string) => ( - - {year} - - )) - )} -
-
- )} - - {event.targetedSections && event.targetedSections.length > 0 && ( -
-

- - Sections -

-
- {event.targetedSections.map((sec: string) => ( - - Section {sec} - - ))} -
-
- )} -
- - {event.guestName && ( -
-

Special Guest

-
-
-

{event.guestName}

- {event.guestSocialProfile && ( - - View Profile - - )} -
-
-
- )} -
- - {/* Footer */} -
- -
- -
- - ); -}; diff --git a/RIT-EMS-main/frontend/src/components/dashboard/EventHistory.tsx b/RIT-EMS-main/frontend/src/components/dashboard/EventHistory.tsx deleted file mode 100644 index 646e85f..0000000 --- a/RIT-EMS-main/frontend/src/components/dashboard/EventHistory.tsx +++ /dev/null @@ -1,387 +0,0 @@ -import { API_BASE_URL } from '../../lib/config'; -import React, { useEffect, useState } from 'react'; -import { motion, AnimatePresence } from 'framer-motion'; -import { - History, - Search, - Calendar, - MapPin, - CheckCircle2, - XCircle, - Clock, - Download, - Filter, - AlertTriangle, - ChevronRight, - User, - Heart, - FileText, - X, - Building2, - Users, - Wallet, - Ticket -} from 'lucide-react'; -import { cn } from '../../lib/utils'; -import { format } from 'date-fns'; -import { Pagination } from './Pagination'; - -interface Event { - id: number; - title: string; - startDate: string; - endDate: string; - type: string; - status: string; - department: string; - location: string; - budget: number; - conflictMessage?: string; - rejectionReason?: string; - institution: string; - category: string; - academicYears: string[]; - proposer?: { - fullName: string; - }; - description?: string; - sponsors?: string[]; - hasRegistrationFee: boolean; - registrationFee: number; -} - -export const EventHistory: React.FC = () => { - const [events, setEvents] = useState([]); - const [searchQuery, setSearchQuery] = useState(''); - const [statusFilter, setStatusFilter] = useState('ALL'); - const [selectedEvent, setSelectedEvent] = useState(null); - const [currentPage, setCurrentPage] = useState(1); - const [itemsPerPage, setItemsPerPage] = useState(10); - - useEffect(() => { - fetch(API_BASE_URL + '/api/events') - .then(res => res.json()) - .then(data => setEvents(data)) - .catch(err => console.error('History fetch failed:', err)); - }, []); - - const getStatusStyle = (status: string, hasConflict: boolean) => { - if (hasConflict && status !== 'APPROVED') return { - bg: 'bg-red-50', - text: 'text-red-600', - border: 'border-red-100', - icon: AlertTriangle, - label: 'CONFLICT' - }; - - switch (status) { - case 'APPROVED': return { bg: 'bg-emerald-50', text: 'text-emerald-600', border: 'border-emerald-100', icon: CheckCircle2, label: 'APPROVED' }; - case 'REQUESTED': return { bg: 'bg-blue-50', text: 'text-blue-600', border: 'border-blue-100', icon: Clock, label: 'REQUESTED' }; - case 'PENDING_PR': return { bg: 'bg-purple-50', text: 'text-purple-600', border: 'border-purple-100', icon: ShieldCheck, label: 'PENDING PRINCIPAL' }; - case 'HOD_REJECTED': - case 'PRINCIPAL_REJECTED': return { bg: 'bg-red-50', text: 'text-red-600', border: 'border-red-100', icon: XCircle, label: 'REJECTED' }; - default: return { bg: 'bg-slate-50', text: 'text-slate-600', border: 'border-slate-100', icon: Clock, label: status }; - } - }; - - const filteredEvents = events - .filter(e => { - const matchesSearch = e.title.toLowerCase().includes(searchQuery.toLowerCase()) || - e.department.toLowerCase().includes(searchQuery.toLowerCase()); - - if (statusFilter === 'ALL') return matchesSearch; - if (statusFilter === 'PENDING') return matchesSearch && (e.status === 'REQUESTED' || e.status === 'PENDING_PR'); - if (statusFilter === 'REJECTED') return matchesSearch && e.status.includes('REJECTED'); - return matchesSearch && e.status === statusFilter; - }) - .sort((a, b) => new Date(b.startDate).getTime() - new Date(a.startDate).getTime()); - - const currentEvents = filteredEvents.slice( - (currentPage - 1) * itemsPerPage, - currentPage * itemsPerPage - ); - - return ( -
- {/* Header Section */} -
-
-
- -
-
-

Institutional Event History

-

Audit-ready comprehensive event ledger

-
-
- -
- -
-
- - {/* Filters Bar */} -
-
- - setSearchQuery(e.target.value)} - className="w-full h-16 pl-16 pr-8 bg-white border border-slate-100 rounded-3xl text-sm font-bold text-text-dark focus:outline-none focus:ring-4 focus:ring-brand-indigo/5 focus:border-brand-indigo transition-all" - /> -
- -
- {['ALL', 'APPROVED', 'PENDING', 'REJECTED'].map(status => ( - - ))} -
-
- - {/* Events Ledger */} -
-
- - - - - - - - - - - - - {currentEvents.map((event, idx) => { - const statusStyle = getStatusStyle(event.status, !!event.conflictMessage); - const StatusIcon = statusStyle.icon; - - return ( - setSelectedEvent(event)} - className="group hover:bg-slate-50/50 transition-colors cursor-pointer" - > - - - - - - - ); - })} - - -
Event DetailsLogisticsStatusBudget
-
-
- {event.department?.slice(0, 3).toUpperCase()} -
-
-

{event.title}

-

{event.type}

-
-
-
-
-
- - {format(new Date(event.startDate), 'MMM d, yyyy')} -
-
- - {event.location} -
-
-
-
- - {statusStyle.label} -
-
- ₹{event.budget?.toLocaleString() || '0'} - - -
-
- - { - setItemsPerPage(val); - setCurrentPage(1); - }} - itemsPerPageOptions={[5, 10, 20, 50]} - /> -
- - {/* Detail Modal */} - - {selectedEvent && ( -
- setSelectedEvent(null)} - className="absolute inset-0 bg-slate-900/40 backdrop-blur-sm" - /> - -
-
-
- Event History - - {selectedEvent.institution} -
-

{selectedEvent.title}

-
- -
- -
- {/* Description */} - {selectedEvent.description && ( -
-
- - Description -
-

- {selectedEvent.description} -

-
- )} - -
-
-
-
- - Date & Time -
-

{new Date(selectedEvent.startDate).toLocaleString()}

-
-
-
- - Location -
-

{selectedEvent.location}

-
-
- -
-
-
- - Department -
-

{selectedEvent.department}

-
-
-
- - Target Batches -
-

{selectedEvent.academicYears?.join(', ') || 'N/A'}

-
-
-
- - {/* Sponsors */} - {selectedEvent.sponsors && selectedEvent.sponsors.length > 0 && ( -
-
- - Event Sponsors -
-
- {selectedEvent.sponsors.map((sponsor, idx) => ( - - {sponsor} - - ))} -
-
- )} - -
-
-
- - Budget -
-

₹{selectedEvent.budget?.toLocaleString() || '0'}

-
-
-
- - Status -
-

{selectedEvent.status}

-
-
- - {selectedEvent.rejectionReason && ( -
-

Rejection Reason

-

{selectedEvent.rejectionReason}

-
- )} -
-
-
- )} -
-
- ); -}; - -const ShieldCheck = (props: any) => ( - - - - -); diff --git a/RIT-EMS-main/frontend/src/components/dashboard/EventProposalForm.tsx b/RIT-EMS-main/frontend/src/components/dashboard/EventProposalForm.tsx deleted file mode 100644 index f44cae7..0000000 --- a/RIT-EMS-main/frontend/src/components/dashboard/EventProposalForm.tsx +++ /dev/null @@ -1,1452 +0,0 @@ -import React, { useState, useEffect, useRef, useMemo } from 'react'; -import { motion, AnimatePresence } from 'framer-motion'; -import { - Calendar, - MapPin, - Building2, - Users, - PlusCircle, - CheckCircle2, - AlertCircle, - ChevronRight, - ShieldCheck, - X, - Split, - Layers, - ArrowRight, - Globe, - Briefcase, - FileText, - Heart, - Wallet, - Zap, - Ticket, - ChevronDown, - AlertTriangle, - FileSpreadsheet -} from 'lucide-react'; -import { useAuth } from '../../context/AuthContext'; -import { cn } from '../../lib/utils'; -import { API_BASE_URL } from '../../lib/config'; -import { INSTITUTIONAL_EVENTS } from '../../constants/institutionalEvents'; -import { getCurrentAcademicYear } from '../../lib/dateUtils'; - -const eventTypes = ['Workshop', 'Seminar', 'Conference', 'Guest Lecture', 'Industrial Visit', 'Techfest', 'Cultural Event', 'Other']; -const ritDepartments = ['AI&DS', 'AI&ML', 'CSE', 'CCE', 'CSBS', 'ECE', 'MECH', 'EE(VLSI)', 'BIOTECH', 'Placement Department', 'H&S Dept']; -const rsbDepartments = ['PGDM']; -const VENUE_LIST = [ - { name: 'N/A', capacity: null }, - { name: 'GB 4th floor auditorium', capacity: 500 }, - { name: 'Wozniak Auditorium', capacity: 180 }, - { name: 'C6-02 Indoor Theatre', capacity: 180 }, - { name: 'H Block Guest Lecture Theatre', capacity: 60 }, - { name: 'Steve Jobs Computer Centre 1', capacity: 120 }, - { name: 'Steve Jobs Computer Centre 2', capacity: 120 }, - { name: 'Others.', capacity: null } -]; -const amenitiesList = [ - 'Sound System', 'Projector', 'Wi-Fi', 'Refreshments', 'Photography', - 'Stage Decor', 'Mementos', 'Certificates', 'Mike/PA System', 'White Board', - 'Lunch', 'Breakfast', 'Guest Transport', 'Remuneration', 'Bouquet', - 'LED Screen', 'Flower decoration', 'Computer lab', 'Board Room', - 'Guest Hospitality', 'Transportation for Guest' -]; - -const CENTRE_MAPPING: Record = { - 'CSE': ['AI Centre', 'Apple iOS App Development Centre', 'Cyber Security Centre'], - 'AI&DS': ['AR, VR & MR Centre', 'Cloud Computing', 'ZF Data Analytics [COE]'], - 'CCE': ['Data Analytics Centre', 'Space Tech Centre'], - 'ECE': ['Centre for IoT', 'RADAR', 'Centre for Image Processing', 'Quantum Computing'], - 'MECH': ['Electric Vehicle & Energy', 'Advanced Manufacturing Centre', 'Robotics and Drone Tech'], - 'Placement Department': ['Placement Cell', 'Incubation cell'] -}; - -interface ClassMapping { - id: number; - institution: string; - department: string; - academicYear: string; - sections: string[]; -} - -interface Event { - id: number; - title: string; - type: string; - status: string; - department: string; - academicYears: string[]; - targetedSections: string[]; -} - -interface EventProposalFormProps { - initialData?: { - department?: string; - eventType?: string; - academicYears?: string[]; - startDate?: string; - isClubEvent?: boolean; - eventName?: string; - id?: number; - isEditMode?: boolean; - endDate?: string; - category?: string; - institution?: string; - venue?: string; - guestName?: string; - socialProfile?: string; - requirements?: string[]; - targetedSections?: string[]; - budget?: string | number; - hasRegistrationFee?: boolean; - registrationFee?: string | number; - paymentLink?: string; - targetDepartments?: string[]; - description?: string; - sponsors?: string[]; - centreName?: string; - isPublicEvent?: boolean; - image?: string; - status?: string; - } | null; -} - -export const EventProposalForm: React.FC = ({ initialData }) => { - const { user } = useAuth(); - const isClubVariant = initialData?.isClubEvent || false; - const isFaculty = user?.role === 'FACULTY'; - const isPlacementCell = user?.isPlacementStaff || user?.role === 'PLACEMENT' || user?.department === 'Placement Department'; - - const [isSubmitting, setIsSubmitting] = useState(false); - const [submitted, setSubmitted] = useState(false); - const [error, setError] = useState(''); - const [classes, setClasses] = useState([]); - const [existingEvents, setExistingEvents] = useState([]); - const [classStrengths, setClassStrengths] = useState([]); - - const fileInputRef = useRef(null); - - const handleImageChange = (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (file) { - const reader = new FileReader(); - reader.onloadend = () => { - const img = new window.Image(); - img.onload = () => { - const canvas = document.createElement('canvas'); - const max_width = 800; - let width = img.width; - let height = img.height; - - if (width > max_width) { - height = Math.round((height * max_width) / width); - width = max_width; - } - - canvas.width = width; - canvas.height = height; - const ctx = canvas.getContext('2d'); - if (ctx) { - ctx.drawImage(img, 0, 0, width, height); - const compressedBase64 = canvas.toDataURL('image/jpeg', 0.7); - setFormData(prev => ({ ...prev, image: compressedBase64 })); - } else { - setFormData(prev => ({ ...prev, image: reader.result as string })); - } - }; - img.src = reader.result as string; - }; - reader.readAsDataURL(file); - } - }; - - const [eventScope, setEventScope] = useState<'INSTITUTIONAL' | 'DEPARTMENT' | 'CLUB' | 'PLACEMENT' | 'CENTRE'>( - initialData?.isClubEvent ? 'INSTITUTIONAL' : (isPlacementCell ? 'PLACEMENT' : 'DEPARTMENT') - ); - const [conflictData, setConflictData] = useState<{ message: string, conflicts: any[], canOverride: boolean } | null>(null); - - const currentAcademicYear = getCurrentAcademicYear(); - - // Filter institutional events that haven't been approved/completed this year - const availableInstitutionalEvents = INSTITUTIONAL_EVENTS.filter(ie => { - return !existingEvents.some(e => - e.title.toLowerCase() === ie.name.toLowerCase() && - (e.status?.toUpperCase() === 'APPROVED' || e.status?.toUpperCase() === 'COMPLETED') && - e.academicYears?.includes(currentAcademicYear) - ); - }); - - const [formData, setFormData] = useState({ - eventName: initialData?.eventName || '', - startDate: initialData?.startDate || '', - endDate: initialData?.endDate || '', - eventType: isClubVariant ? 'CLUB' : (initialData?.eventType || 'Guest Lecture'), - category: isClubVariant ? 'CLUB' : (initialData?.category || 'ACADEMIC'), - institution: initialData?.institution || 'RIT', - department: initialData?.department || (isFaculty ? (user?.department || 'CSE') : 'CSE'), - academicYears: initialData?.academicYears || [] as string[], - venue: initialData?.venue || 'N/A', - customVenue: '', - guestName: initialData?.guestName || '', - socialProfile: initialData?.socialProfile || '', - requirements: initialData?.requirements || [] as string[], - targetedSections: initialData?.targetedSections || [] as string[], - budget: initialData?.budget || '' as string | number, - customEventType: '', - hasRegistrationFee: initialData?.hasRegistrationFee || false, - registrationFee: initialData?.registrationFee || '' as string | number, - paymentLink: initialData?.paymentLink || '', - targetDepartments: initialData?.targetDepartments || (isFaculty ? (isPlacementCell ? [] : [user?.department || 'CSE']) : [] as string[]), - allDepts: false, - allBatches: false, - allSections: false, - description: initialData?.description || '', - sponsors: initialData?.sponsors || [] as string[], - centreName: initialData?.centreName || (eventScope === 'CENTRE' ? ((CENTRE_MAPPING[user?.department || ''] || CENTRE_MAPPING['Placement Department'] || [])[0] || '') : ''), - isPublicEvent: initialData?.isPublicEvent || false, - image: initialData?.image || '', - status: initialData?.status || 'REQUESTED', - targetedBatch: (initialData as any)?.targetedBatch || '' - }); - - const [newSponsor, setNewSponsor] = useState(''); - const [showAlternateEvent, setShowAlternateEvent] = useState(false); - const [alternateEvent, setAlternateEvent] = useState({ - eventName: '', - startDate: '', - endDate: '', - venue: 'N/A', - customVenue: '', - }); - - useEffect(() => { - // Reset event name and update default event type on scope change - const availableCentres = CENTRE_MAPPING[user?.department || ''] || CENTRE_MAPPING['Placement Department'] || []; - setFormData(prev => ({ - ...prev, - eventName: '', - eventType: eventScope === 'INSTITUTIONAL' ? 'Institutional' : - eventScope === 'CLUB' ? 'Club' : - eventScope === 'PLACEMENT' ? 'Placement' : '', - category: eventScope === 'CENTRE' ? 'CENTRE' : (eventScope === 'CLUB' ? 'CLUB' : 'ACADEMIC'), - centreName: eventScope === 'CENTRE' ? (availableCentres[0] || '') : prev.centreName - })); - }, [eventScope, user?.department]); - - const [batches, setBatches] = useState([]); - - useEffect(() => { - fetchClasses(); - fetchExistingEvents(); - fetchClassStrengths(); - fetchBatches(); - }, []); - - const fetchBatches = async () => { - try { - const response = await fetch(API_BASE_URL + '/api/batches'); - if (response.ok) { - const data = await response.json(); - setBatches(data); - } - } catch (err) { - console.error('Failed to fetch batches:', err); - } - }; - - const deptBatches = useMemo(() => { - const dept = eventScope === 'DEPARTMENT' ? formData.department : (user?.department || 'CSE'); - return batches.filter(b => b.department === dept); - }, [batches, formData.department, eventScope, user?.department]); - - const fetchClassStrengths = async () => { - try { - const response = await fetch(API_BASE_URL + '/api/admin/users'); - if (response.ok) { - const data = await response.json(); - const strengths = data - .filter((u: any) => u.isClassIncharge) - .map((u: any) => ({ - dept: u.inchargeClass, - year: u.inchargeBatch, - sec: u.inchargeSection, - strength: u.classStrength || 0 - })); - setClassStrengths(strengths); - } - } catch (err) { - console.error('Failed to fetch class strengths:', err); - } - }; - - const fetchClasses = async () => { - try { - const response = await fetch(API_BASE_URL + '/api/classes'); - if (response.ok) { - const data = await response.json(); - setClasses(data); - } - } catch (err) { - console.error('Failed to fetch classes:', err); - } - }; - - const fetchExistingEvents = async () => { - try { - const response = await fetch(API_BASE_URL + '/api/events'); - if (response.ok) { - const data = await response.json(); - setExistingEvents(data); - } - } catch (err) { - console.error('Failed to fetch events:', err); - } - }; - - const availableYears = Array.from(new Set( - classes - .filter(c => c.institution.trim() === formData.institution.trim() && - (eventScope === 'INSTITUTIONAL' || eventScope === 'CLUB' || eventScope === 'PLACEMENT' || (eventScope === 'DEPARTMENT' && isPlacementCell) ? true : c.department.trim() === formData.department.trim())) - .map(c => c.academicYear) - )).sort(); - - const availableSections = classes - .filter(c => - c.institution.trim() === formData.institution.trim() && - ((eventScope === 'DEPARTMENT' || eventScope === 'PLACEMENT') ? ( - eventScope === 'DEPARTMENT' ? c.department.trim() === formData.department.trim() : formData.targetDepartments.includes(c.department.trim()) - ) : true) && - formData.academicYears.includes(c.academicYear.trim()) - ) - .reduce((acc, curr) => [...acc, ...curr.sections], [] as string[]); - - const toggleSelection = (field: 'academicYears' | 'targetedSections' | 'targetDepartments' | 'requirements', value: string) => { - setFormData(prev => { - const current = prev[field] as string[]; - const exists = current.includes(value); - const updated = exists ? current.filter(v => v !== value) : [...current, value]; - - if (field === 'academicYears') return { ...prev, academicYears: updated, allBatches: false }; - if (field === 'targetDepartments') return { ...prev, targetDepartments: updated, allDepts: false }; - if (field === 'targetedSections') return { ...prev, targetedSections: updated, allSections: false }; - return { ...prev, [field]: updated }; - }); - }; - - const addSponsor = () => { - if (newSponsor.trim()) { - setFormData(prev => ({ ...prev, sponsors: [...prev.sponsors, newSponsor.trim()] })); - setNewSponsor(''); - } - }; - - const removeSponsor = (index: number) => { - setFormData(prev => ({ ...prev, sponsors: prev.sponsors.filter((_, i) => i !== index) })); - }; - - const isSectionDisabled = (section: string) => { - if (formData.eventType === 'Other') return false; - return existingEvents.some(e => { - const status = e.status?.toUpperCase(); - const isActive = status === 'APPROVED' || status === 'COMPLETED' || status === 'PENDING_PR' || status === 'REQUESTED'; - return e.type?.toLowerCase() === formData.eventType?.toLowerCase() && - isActive && - e.targetedSections?.includes(section) && - formData.academicYears.some(y => e.academicYears?.includes(y)); - }); - }; - - const leftOutSections = availableSections.filter(s => - !formData.targetedSections.includes(s) && - !isSectionDisabled(s) - ); - - const totalExpectedStrength = React.useMemo(() => { - const deptsToTarget = (eventScope === 'INSTITUTIONAL' || eventScope === 'CLUB' || eventScope === 'PLACEMENT' || (eventScope === 'DEPARTMENT' && isPlacementCell)) ? formData.targetDepartments : [formData.department]; - const batchesToTarget = formData.allBatches ? availableYears : formData.academicYears; - let total = 0; - - for (const d of deptsToTarget) { - for (const y of batchesToTarget) { - const availableSecsForThisCombo = classes - .filter(c => c.department?.trim() === d?.trim() && c.academicYear?.trim() === y?.trim() && c.institution?.trim() === formData.institution?.trim()) - .reduce((acc, curr) => [...acc, ...curr.sections], [] as string[]); - - const sectionsToTarget = formData.allSections ? availableSecsForThisCombo : formData.targetedSections.filter(s => availableSecsForThisCombo.includes(s)); - - for (const s of sectionsToTarget) { - const match = classStrengths.find(cs => cs.dept === d && cs.year === y && cs.sec === s); - if (match) { - total += match.strength; - } - } - } - } - return total; - }, [formData.targetDepartments, formData.department, formData.academicYears, formData.targetedSections, formData.allBatches, formData.allSections, formData.institution, classStrengths, eventScope, isPlacementCell, availableYears, classes]); - - const filteredVenues = VENUE_LIST.filter(v => v.capacity === null || v.capacity >= totalExpectedStrength); - - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setIsSubmitting(true); - setError(''); - - const now = new Date(); - const start = new Date(formData.startDate); - const end = new Date(formData.endDate); - - if (start < now) { - setError('Cannot schedule events in the past. Please select a future date and time.'); - setIsSubmitting(false); - return; - } - - if (end <= start) { - setError('End date must be after the start date.'); - setIsSubmitting(false); - return; - } - - const groupRequestId = crypto.randomUUID(); - const batchesToAssign = formData.allBatches ? availableYears : formData.academicYears; - let deptsToCreate = (eventScope === 'CLUB' || eventScope === 'PLACEMENT' || (eventScope === 'DEPARTMENT' && isPlacementCell)) ? formData.targetDepartments : [formData.department]; - - // For institutional events, create only ONE global event record - if (eventScope === 'INSTITUTIONAL') { - deptsToCreate = ['Institutional']; - } - - if (eventScope === 'CENTRE' && !formData.centreName) { - setError('Please select a centre.'); - setIsSubmitting(false); - return; - } - - if (deptsToCreate.length === 0) { - setError(`Please select at least one target department for this ${eventScope.toLowerCase()} event.`); - setIsSubmitting(false); - return; - } - - if (eventScope !== 'CENTRE' && batchesToAssign.length === 0) { - setError('Please select at least one target batch.'); - setIsSubmitting(false); - return; - } - - try { - if (initialData?.isEditMode && initialData.id) { - const updatePayload = { - ...formData, - title: formData.eventName, - userId: user?.id, - budget: formData.budget === '' ? 0 : Number(formData.budget), - registrationFee: formData.hasRegistrationFee ? Number(formData.registrationFee) : 0, - status: formData.status - }; - - const res = await fetch(`${API_BASE_URL}/api/events/${initialData.id}`, { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(updatePayload), - }); - - if (!res.ok) { - const err = await res.json(); - throw new Error(err.message || 'Update failed'); - } - } else { - for (const dept of deptsToCreate) { - // Filter sections that belong to THIS department - const deptSections = (eventScope === 'DEPARTMENT' || eventScope === 'PLACEMENT') - ? formData.targetedSections.filter(s => - classes.some(c => c.department.trim() === dept.trim() && c.sections.includes(s)) - ) - : []; - - // If it's a placement event and we're selective, only create for depts with selected sections - if (eventScope === 'PLACEMENT' && formData.targetedSections.length > 0 && deptSections.length === 0) { - continue; - } - - const primaryPayload = { - ...formData, - department: dept, - venue: formData.venue === 'Others.' ? formData.customVenue : formData.venue, - groupRequestId, - academicYears: batchesToAssign, - targetedSections: deptSections, - userId: user?.id, - budget: formData.budget === '' ? 0 : Number(formData.budget), - registrationFee: formData.hasRegistrationFee ? Number(formData.registrationFee) : 0, - category: eventScope === 'CLUB' ? 'CLUB' : (eventScope === 'INSTITUTIONAL' ? 'INSTITUTIONAL' : (eventScope === 'CENTRE' ? 'CENTRE' : 'ACADEMIC')), - eventType: formData.eventType, - centreName: eventScope === 'CENTRE' ? formData.centreName : undefined, - isPublicEvent: eventScope === 'CENTRE' ? formData.isPublicEvent : undefined, - image: formData.image - }; - - const res = await fetch(API_BASE_URL + '/api/events/propose', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - ...primaryPayload, - cancelConflicting: false - }), - }); - - if (!res.ok) { - const err = await res.json(); - if (res.status === 409 && err.canOverride) { - setConflictData(err); - setIsSubmitting(false); - return; - } - throw new Error(`[${dept}] ${err.message || 'Submission failed'}`); - } - - if (!formData.allSections && showAlternateEvent && (eventScope === 'DEPARTMENT' || eventScope === 'PLACEMENT') && leftOutSections.length > 0) { - const deptLeftOut = leftOutSections.filter(s => - classes.some(c => c.department.trim() === dept.trim() && c.sections.includes(s)) - ); - - if (deptLeftOut.length > 0) { - const altPayload = { - ...formData, - department: dept, - groupRequestId, - eventName: alternateEvent.eventName || `${formData.eventName} (Division 2)`, - startDate: alternateEvent.startDate || formData.startDate, - endDate: alternateEvent.endDate || formData.endDate, - venue: alternateEvent.venue === 'Others.' ? alternateEvent.customVenue : alternateEvent.venue, - targetedSections: deptLeftOut, - academicYears: batchesToAssign, - userId: user?.id, - budget: 0, - registrationFee: formData.hasRegistrationFee ? Number(formData.registrationFee) : 0, - eventType: formData.eventType - }; - - await fetch(API_BASE_URL + '/api/events/propose', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(altPayload), - }); - } - } - } - } - setSubmitted(true); - } catch (err: any) { - setError(err.message); - } finally { - setIsSubmitting(false); - } - }; - - if (submitted) { - return ( -
- -

Proposals Submitted!

-

Your event proposals have been successfully queued for approval.

- -
- ); - } - - return ( -
- {(user?.role === 'ADMIN' || user?.role === 'PRINCIPAL') && ( - -
-
- -
-
-

Bulk Import via Excel

-

Have many events? Upload a spreadsheet instead.

-
-
- -
- )} - -
- {!isPlacementCell && ( - - )} - {(isFaculty || isPlacementCell) && ( - - )} - {!isPlacementCell && ( - - )} - {user?.isClubCoordinator && ( - - )} - {isPlacementCell && ( - - )} -
- -
-
-
-

- {eventScope === 'INSTITUTIONAL' ? 'Institutional Proposal' : - eventScope === 'CLUB' ? 'Club Proposal' : - eventScope === 'CENTRE' ? 'Centre Event Proposal' : - eventScope === 'PLACEMENT' ? 'Placement Coordinator Schedule' : 'Departmental Proposal'} -

-

- {isFaculty ? `Faculty of ${user?.department}` : 'Administrative Portal'} -

-
- -
- -
-
- {(eventScope === 'DEPARTMENT' || eventScope === 'CENTRE') ? ( - <> -
- -
- - -
-
-
- - setFormData({...formData, eventName: e.target.value})} - className="w-full bg-slate-50 border border-transparent rounded-2xl py-4 px-6 text-sm font-semibold focus:bg-white focus:border-brand-indigo/30 transition-all" - placeholder="e.g. Workshop on Generative AI" - /> -
- - ) : eventScope === 'INSTITUTIONAL' ? ( -
- -
- - -
-
- ) : ( -
- - setFormData({...formData, eventName: e.target.value, eventType: eventScope === 'CLUB' ? 'Club' : 'Placement'})} - className="w-full bg-slate-50 border border-transparent rounded-2xl py-4 px-6 text-sm font-semibold focus:bg-white focus:border-brand-indigo/30 transition-all" - placeholder={eventScope === 'PLACEMENT' ? "Enter placement activity name..." : "Enter event title..."} - /> -
- )} - - {initialData?.isEditMode && user?.role === 'ADMIN' && ( -
- -
- - -
-
- )} - -
- -
- -