Skydiving App: Build A Mentor-Mentee Scheduler
Hey guys! Let's dive into the exciting world of full-stack web development with a project that's both challenging and rewarding: building a skydiving mentor-mentee scheduler and progression app. This isn't just about coding; it's about creating a real-world solution for skydiving training centers. We're talking about a production-ready application that handles everything from scheduling to tracking progression, all while ensuring safety and fairness in the skies. So, buckle up, and let's get started!
Project Overview
At its core, this project aims to create a comprehensive web application that streamlines the process of pairing skydiving mentors with mentees, tracking their progress, and managing schedules. Imagine a system where mentors can easily input their availability, mentees can request sessions, and the app intelligently matches them based on various factors. This app also incorporates a progression program, complete with signoffs, badges, and even some gamification elements to keep things engaging.
This project isn't just a theoretical exercise; it's a practical application of full-stack development principles. We'll be tackling everything from database design to user interface implementation, ensuring that the final product is robust, user-friendly, and scalable. Plus, it's a fantastic opportunity to learn and apply industry best practices in areas like authentication, security, and performance optimization. Let's explore the specific goals and features we'll be building into this epic skydiving app.
Key Goals of the Skydiving App
Before we get into the nitty-gritty, let's outline the primary objectives of our skydiving app. These goals will serve as our guiding stars throughout the development process, ensuring that we stay focused and deliver a product that truly meets the needs of a skydiving training center:
- Availability and Attendance Collection: The app should efficiently gather information on mentor availability and mentee attendance for specific days and time blocks. This involves creating a user-friendly interface where mentors can input their schedules and mentees can request sessions, setting the stage for optimal matching.
- Intelligent Matching: At the heart of the app lies its matching algorithm. Our goal is to assign mentees to mentors, ideally targeting two mentees per mentor per block, while adhering to fairness principles and various constraints. This includes factors like mentor capacity, mentee preferences, and compatibility levels.
- Progression Tracking: Skydiving is a skill-based activity, and our app needs to reflect that. We'll implement a system to track a belly (RW) progression program, incorporating 2-way and 3-way drills, signoffs, badges, and basic gamification elements. This will provide a clear pathway for mentees to advance their skills.
Tech Stack and Constraints
Now, let's talk tech! Choosing the right tools is crucial for any software project, and this one is no exception. We'll be working with a modern tech stack that's both powerful and versatile, allowing us to build a robust and scalable application. Here’s a breakdown of the technologies we'll be using:
- Backend: Our backend will be built using Python, a popular language known for its readability and extensive libraries. We'll leverage FastAPI, a modern, high-performance web framework, to create our APIs. For data storage, we'll use Postgres, a robust and reliable relational database, along with SQLAlchemy as our ORM (Object-Relational Mapper) and Alembic for database migrations. Pydantic will help us with data validation and serialization.
- Matching Worker: To handle the complex task of matching mentors and mentees, we'll use APScheduler for cron jobs. If the need arises, we might also incorporate Celery and Redis for more advanced job management.
- Authentication: Security is paramount, so we'll implement JWT (JSON Web Token) session cookies for authentication. We'll also incorporate role-based access control (RBAC) to manage permissions for mentors, mentees, and admins.
- Frontend: On the frontend, we'll be using React 18, a powerful JavaScript library for building user interfaces. Vite will serve as our build tool, and TypeScript will add type safety to our code. React Router will handle navigation, TanStack Query will manage API data, Tailwind will provide styling, and shadcn/ui will offer pre-built UI components.
- Infrastructure: We'll use Docker and docker-compose for local development, ensuring consistency across environments. The app will follow the 12-factor methodology, utilizing environment variables for configuration.
- Testing: To ensure code quality, we'll use Pytest for backend testing, React Testing Library and Vitest for frontend testing, and Playwright for end-to-end (E2E) testing.
- Observability: We'll implement structured JSON logs, request metrics, and OpenAPI docs at
/docs
to monitor and debug our application effectively. - Time Zone Handling: To accommodate users in different time zones, we'll store times in UTC and display them in the user's local time zone.
This tech stack provides a solid foundation for building a scalable and maintainable application. It also allows us to leverage modern development practices and tools, making the development process more efficient and enjoyable. Now, let's dive into how we'll organize our code.
Repository Layout
Organizing our code is crucial for maintainability and collaboration. A well-structured repository makes it easier to navigate the codebase, understand the project's architecture, and contribute effectively. Here’s how we'll structure our project:
/app
/backend
main.py
/api
/core (auth, settings, rbac)
/db (models, schemas, migrations)
/services (matching, progression, notifications)
/tasks (scheduled jobs)
/tests
/frontend
index.html
/src
/pages
/components
/api (client)
/store
/tests
docker-compose.yml
Dockerfile.backend
Dockerfile.frontend
README.md
Let's break down each directory:
- /backend: This directory houses all the backend code. It includes:
main.py
: The entry point of our FastAPI application./api
: Contains the API route definitions./core
: Includes core functionalities such as authentication, settings, and role-based access control./db
: Defines database models, schemas, and Alembic migrations./services
: Contains business logic for matching, progression tracking, and notifications./tasks
: Houses scheduled jobs./tests
: Includes backend tests.
- /frontend: This directory contains all the frontend code. It includes:
index.html
: The main HTML file./src
:/pages
: Contains the different pages of the application./components
: Includes reusable UI components./api
: Defines the API client./store
: Manages the application's state./tests
: Includes frontend tests.
docker-compose.yml
: Defines the Docker Compose configuration for local development.Dockerfile.backend
: Specifies the Docker configuration for the backend.Dockerfile.frontend
: Specifies the Docker configuration for the frontend.README.md
: Provides project documentation and setup instructions.
This structure provides a clear separation of concerns, making it easier to develop, test, and maintain the application. With our code organization in place, let's move on to the heart of our application: the data model.
Data Model (Postgres)
The data model is the backbone of any application that deals with data. It defines how data is structured and stored, influencing everything from application performance to data integrity. For our skydiving app, we'll be using Postgres, a powerful and reliable relational database. Here’s a breakdown of the key tables and their fields:
- users: This table stores user information.
id
(UUID, Primary Key)role
(enum: mentor, mentee, admin)name
email
(unique)phone
uspa_license
jumps
(int)is_active
(bool)created_at
- mentors: This table stores mentor-specific information.
id
(UUID, Primary Key, Foreign Key to users.id)ratings
(text)coach_number
(text)disciplines
(text[])max_concurrent_mentees
(int, default 2)seniority_score
(int, default 0)dz_endorsement
(bool)
- mentees: This table stores mentee-specific information.
id
(UUID, Primary Key, Foreign Key to users.id)goals
(text)comfort_level
(enum: low, medium, high)canopy_size
(int)last_currency_date
(date)
- availability: This table stores mentor availability.
id
(UUID)user_id
(UUID, Foreign Key to users.id)role
day_of_week
(int)start_time
(time)end_time
(time)start_date
(date)end_date
(date)is_recurring
(bool)capacity_override
(int, nullable)
- session_blocks: This table defines session blocks.
id
(UUID)date
(date)start_time
(time)end_time
(time)dz_id
(UUID, nullable)load_interval_min
(int)block_capacity_hint
(int)
- attendance_requests: This table tracks mentee attendance requests.
id
(UUID)mentee_id
(UUID, Foreign Key to mentees.id)session_block_id
(UUID, Foreign Key to session_blocks.id)status
(enum: pending, confirmed, cancelled)
- preferences: This table stores mentee preferences for mentors.
id
(UUID)mentee_id
(UUID, Foreign Key to mentees.id)preferred_mentors
(UUID[], default {})avoid_mentors
(UUID[], default {})notes
(text)
- assignments: This table tracks mentor-mentee assignments.
id
(UUID)session_block_id
(UUID, Foreign Key to session_blocks.id)mentor_id
(UUID, Foreign Key to mentors.id)mentee_id
(UUID, Foreign Key to mentees.id)status
(enum: pending, confirmed, declined, cancelled)created_at
- progression_steps: This table defines progression steps.
id
(UUID)code
(unique)title
description
category
(enum: 2way, 3way, canopy)required
(bool)min_jumps_gate
(int, default 0)references
(jsonb)
- step_completions: This table tracks completed progression steps.
id
(UUID)mentee_id
(UUID, Foreign Key to mentees.id)step_id
(UUID, Foreign Key to progression_steps.id)mentor_id
(UUID)completed_at
(timestamp)evidence_url
(text)notes
(text)
- badges: This table defines badges.
id
(UUID)code
(unique)name
description
criteria_json
- awards: This table tracks awarded badges.
id
(UUID)mentee_id
(UUID, Foreign Key to mentees.id)badge_id
(UUID, Foreign Key to badges.id)awarded_at
(timestamp)
- jump_logs: This table stores jump logs.
id
(UUID)mentee_id
(UUID, Foreign Key to mentees.id)date
(date)jump_number
(int)aircraft
(text)exit_alt
(int)freefall_time
(int)deployment_alt
(int)pattern_notes
(text)drill_ref
(text)mentor_id
(UUID)
- audit_events: This table logs audit events.
id
(UUID)actor_id
(UUID)type
(text)payload_json
(jsonb)at
(timestamp)
We'll also provide Alembic migrations to manage database schema changes. This data model forms the foundation for our application's functionality, enabling us to store and retrieve the information we need to power our skydiving mentor-mentee system. Next up, let's look at seeding the database with some initial data.
Seed Data
To get our app up and running quickly, we'll seed the database with some initial data. This includes creating users, setting up availability, and populating the progression catalog. Here’s what we'll seed:
- Users: We'll create 10 mentors and 24 mentees. This provides a realistic number of users to test the matching algorithm and other features.
- Availability: We'll set up recurring availability for mentors on Tuesdays, Thursdays, Saturdays, and Sundays. This ensures that there are regular opportunities for mentorship sessions.
- Session Blocks: We'll create 6 session blocks per day, spanning from 08:00 to 16:00, with 90-minute blocks. This provides a structured schedule for mentorship sessions.
- Progression Catalog: We'll insert a starter progression catalog with common 2-way and 3-way drills. We'll use placeholder references so admins can link DZ (Drop Zone) documents later. This catalog will serve as a starting point for mentees to track their progress.
- Badges: We'll create badges for milestones like First Star, Donut Spinner, Pod Master, Orbit Ace, Streak-3, and Streak-6. These badges will add a gamification element to the app, motivating mentees to achieve their goals.
Seeding the database allows us to start testing the core functionalities of the app right away. With our initial data in place, let's explore the heart of our application: the matching logic.
Matching Logic
The matching logic is the engine that drives our skydiving app. It's responsible for pairing mentors and mentees in a way that's fair, efficient, and considers various constraints and preferences. We'll be implementing a capacitated bipartite match per session block, which is a fancy way of saying we'll match mentors and mentees based on their capacity and compatibility within each session block. Let's break down the compatibility rules and scoring function we'll be using.
Compatibility Rules
Before we can score potential matches, we need to ensure that certain compatibility rules are met. These rules act as filters, ensuring that only eligible mentors and mentees are considered for pairing:
- Availability Overlap: The mentor and mentee must both be available for the session block's date and time. This is a fundamental requirement to ensure that both parties can attend the session.
- Mentor Capacity: We need to respect the mentor's
max_concurrent_mentees
(default 2) or theavailability.capacity_override
. This ensures that mentors aren't overloaded and can provide adequate attention to each mentee. - Preference Filter (Optional): We'll consider
avoid_mentors
andpreferred_mentors
. Mentees can specify mentors they prefer or want to avoid, and our algorithm will take these preferences into account. - Fall-Rate Compatibility Proxy: We'll use
comfort_level
as a proxy for fall-rate compatibility. Mentees with similar comfort levels are more likely to be a good match, as they'll have similar freefall speeds.
Scoring Function
Once we've filtered out incompatible matches, we need a way to score the remaining potential pairings. Our scoring function will assign a numerical value to each mentor-mentee pair, allowing us to rank them and select the best matches. Here's the scoring function we'll use:
score = 10 * preference_match
+ 5 * fall_rate_compat
+ 3 * mentor_seniority_bucket
- 4 * recent_pairing_penalty(mentor, mentee, lookback=14 days)
- 2 * load_balance_penalty(mentor_recent_load)
Let's break down each component of the score:
10 * preference_match
: This term gives a high weight to mentee preferences. If a mentee has marked a mentor as preferred, this score will be higher. Conversely, if a mentee has marked a mentor to avoid, this score will be lower.5 * fall_rate_compat
: This term rewards matches between mentees and mentors with compatible comfort levels. Mentees with similar comfort levels are more likely to have a productive session.3 * mentor_seniority_bucket
: This term gives a slight boost to more senior mentors. Seniority can be a valuable asset in mentorship, so we want to encourage pairings with experienced mentors.-4 * recent_pairing_penalty(mentor, mentee, lookback=14 days)
: This term penalizes recent pairings between the same mentor and mentee. This promotes variety and ensures that mentees have the opportunity to work with different mentors.-2 * load_balance_penalty(mentor_recent_load)
: This term penalizes mentors who have been heavily loaded recently. This helps to balance the workload among mentors and prevents burnout.
Matching Algorithm
With our compatibility rules and scoring function in place, we can now outline the matching algorithm:
- Expand Mentor Slots: For each block, we expand each mentor into N slots, where N is the mentor's capacity (
max_concurrent_mentees
oravailability.capacity_override
). This allows us to model the capacity constraint in our matching algorithm. - Build Edges: We build edges between eligible mentees and mentor slots, with the edge weight being the score calculated using our scoring function.
- Run Maximum Weight Matching: We run a maximum weight matching algorithm on the slot graph. This algorithm finds the set of edges that maximizes the total score, effectively pairing mentees with the most suitable mentors. We can use libraries like networkx or implement a custom Hungarian variant on the slot graph.
- Create Pending Assignments: We create pending assignments based on the matching results. These assignments are initially pending, giving mentors the opportunity to confirm or decline them.
- Handle Declines: Mentors can confirm or decline assignments within a configurable window. If a mentor declines an assignment, it triggers a reflow, where we re-run the matching algorithm on the remaining candidates.
This matching logic ensures that mentors and mentees are paired in a way that's fair, efficient, and considers various factors. Now that we have our matching logic in place, let's look at how we'll schedule the matching process.
Scheduler
To automate the matching process, we'll implement a scheduler that runs the matching algorithm at regular intervals. This scheduler will ensure that mentors and mentees are paired in a timely manner, without manual intervention. Here’s how our scheduler will work:
- Nightly Matching: The scheduler will run nightly at 18:00 local time. This ensures that the matching process is run when the system load is typically lower, and that mentors and mentees have ample time to plan their sessions for the next day.
- 7-Day Lookahead: The scheduler will run matching for blocks in the next 7 days. This provides a buffer, allowing mentors and mentees to plan their schedules in advance.
- On-Demand Matching: We'll also provide an endpoint for admins to re-run matching for a specific date. This is useful for handling exceptions or making adjustments as needed.
We'll be using APScheduler for our scheduling needs, which is a powerful and flexible library for scheduling tasks in Python. If our scheduling needs become more complex, we might also consider using Celery and Redis for distributed task management.
With our scheduler in place, we can automate the matching process and ensure that mentors and mentees are paired efficiently. Now, let's dive into the REST API contract that will power our application.
REST API Contract
A well-defined REST API contract is essential for building a robust and scalable application. It provides a clear interface for the frontend to interact with the backend, ensuring that data is exchanged in a consistent and predictable manner. Here’s an overview of the REST API endpoints we'll be implementing:
Auth
POST /auth/signup
: Registers a new user.POST /auth/login
: Logs in an existing user.POST /auth/logout
: Logs out the current user.GET /auth/me
: Retrieves the current user's profile.
Profiles
GET /users/:id
: Retrieves a user's profile by ID.PUT /me
: Updates the current user's profile.
Availability
POST /availability
: Creates a new availability entry. The request body should include fields likeday_of_week
,start_time
,end_time
,start_date
,end_date
,is_recurring
, andcapacity_override
.GET /availability?user_id=...
: Retrieves availability entries for a specific user.DELETE /availability/:id
: Deletes an availability entry.
Sessions
GET /sessions?date=YYYY-MM-DD
: Retrieves session blocks for a specific date.POST /sessions/materialize (admin)
: Creates session blocks for a date range. The request body should includefrom
,to
, and atemplate
object withstart
,end
, andinterval_min
.
Attendance and Preferences
POST /attendance
: Creates an attendance request. The request body should includesession_block_id
.DELETE /attendance/:id
: Deletes an attendance request.PUT /preferences
: Updates mentee preferences. The request body should includepreferred_mentors
(an array of UUIDs),avoid_mentors
(an array of UUIDs), andnotes
.
Matching
POST /match/run?date=YYYY-MM-DD (admin)
: Runs the matching algorithm for a specific date.GET /assignments?user_id=...
: Retrieves assignments for a specific user.POST /assignments/:id/confirm
: Confirms an assignment.POST /assignments/:id/decline
: Declines an assignment.
Progression and Jumps
GET /progression/steps?category=2way|3way
: Retrieves progression steps for a specific category.POST /progression/:step_id/complete
: Marks a progression step as complete. The request body should includeevidence_url
andnotes
.POST /jumps
: Creates a new jump log entry. The request body should include fields likedate
,jump_number
,exit_alt
,deployment_alt
,drill_ref
,mentor_id
, andnotes
.GET /awards?mentee_id=...
: Retrieves awards for a specific mentee.
Admin
GET /admin/roster?date=YYYY-MM-DD
: Retrieves aggregated capacity and pairings for a specific date.POST /admin/steps
: Creates or updates progression steps.GET /admin/stats?from=...&to=...
: Retrieves statistics for a date range.
We'll be using OpenAPI 3 to document our API, and we'll validate all requests using Pydantic. This ensures that our API is well-defined and that data is exchanged in a consistent manner.
With our REST API contract in place, let's shift our focus to the frontend requirements of our application.
Frontend Requirements
The frontend is the face of our application, and it's crucial that it's user-friendly, intuitive, and visually appealing. We'll be building a React-based frontend that allows mentors, mentees, and admins to interact with the system effectively. Here’s a breakdown of the key pages and components we'll be implementing.
Pages
Our frontend will consist of several pages, each catering to a specific user role and function:
- Public Pages:
- Landing: A public-facing landing page that introduces the app and its features.
- Login: A login page for existing users to access the system.
- Signup: A signup page for new users to create an account. This page will include role selection (mentor, mentee, admin).
- Mentor Portal:
- Availability Calendar: A calendar view where mentors can input their availability, including recurring availability and exceptions.
- Assignment Inbox: A list of pending assignments that mentors can confirm or decline.
- Post-Jump Notes and Signoffs: A form where mentors can record notes and sign off on step completions after a jump.
- Mentee Portal:
- “I am coming” Planner: A planner where mentees can indicate their attendance for specific dates and view available session blocks.
- Preference Editor: A form where mentees can specify their preferred mentors and mentors to avoid.
- Assignments Timeline: A timeline view of assignments, including meeting points, load windows, and a simple manifest.
- Progression Board: A board that displays drills, status, and earned badges, allowing mentees to track their progress.
- Admin Dashboard:
- Capacity Heatmap: A visual representation of capacity per day and block.
- Run Matching and Preview: An interface for admins to run the matching algorithm and preview the results before publishing.
- Waitlist View: A view of mentees on the waitlist, with options for manual overrides.
- Export CSV or Print Manifest: Functionality to export data to CSV or print a manifest.
Components
To ensure code reusability and maintainability, we'll be building several reusable components:
ScheduleGrid
: A component for displaying schedules in a grid format.AvailabilityEditor
: A component for editing availability.AssignmentCard
: A component for displaying assignment information.ProgressionStepCard
: A component for displaying progression steps.BadgePill
: A component for displaying badges.RosterTable
: A component for displaying rosters.
Technologies and UX
We'll be using TanStack Query for all API calls, which provides features like caching and optimistic updates. Toasts will be used for confirmations and declines, providing immediate feedback to the user. We'll also ensure that the frontend is accessible, with keyboard navigable forms, aria-labels, and color contrast compliance.
Here are some UX rules we'll be following:
- Mentor capacity per block defaults to 2, but can be edited per availability entry.
- If supply is low, we'll allow 1 mentee per mentor and flag the block as under-subscribed.
- If over-subscribed, we'll place mentees on a waitlist ordered by fairness score and show the expected chance of getting a slot.
With our frontend requirements defined, let's move on to notifications, which will play a crucial role in keeping users informed.
Notifications
Notifications are a key component of any application that requires timely communication between users. In our skydiving app, notifications will be used to inform mentors and mentees about assignments, reminders, and changes. Here’s how we'll handle notifications:
- Email Notifications: We'll send email notifications for the following events:
- Mentor assignment pending: When a mentor receives a new assignment.
- Reminder T-24h: A reminder 24 hours before a scheduled session.
- Changes: When there are changes to assignments or schedules.
- Email Templates: We'll create email templates for each type of notification to ensure a consistent and professional look.
- Local Development: For local development, we'll write emails to the console and file. This allows us to test notifications without sending actual emails.
Notifications will help keep mentors and mentees informed and engaged with the app. Now, let's discuss security and privacy, which are paramount in any application that handles user data.
Security and Privacy
Security and privacy are non-negotiable aspects of any modern web application. We'll be implementing several measures to protect user data and ensure the security of our skydiving app. Here’s an overview of the security and privacy measures we'll be taking:
- Authentication: We'll use JWT (JSON Web Token) httpOnly cookies for authentication. This provides a secure way to manage user sessions. We'll use short-lived access tokens and long-lived refresh tokens to minimize the risk of token compromise.
- Rate Limiting: We'll implement rate limiting for auth endpoints to prevent brute-force attacks.
- Role-Based Access Control (RBAC): We'll use server-side validation for role-restricted routes. This ensures that only authorized users can access certain parts of the application.
- Data Protection: We'll never expose medical notes to mentees, ensuring the privacy of sensitive information.
- GDPR Compliance: We'll provide GDPR-style export and delete endpoints for user data. This allows users to export their data or request its deletion, in compliance with GDPR regulations.
Security and privacy are ongoing concerns, and we'll continue to monitor and improve our security measures as needed. With security in mind, let's consider the performance of our application.
Performance
Performance is a critical factor in the user experience. A slow application can lead to frustration and abandonment, while a fast application can improve user engagement and satisfaction. We'll be implementing several strategies to optimize the performance of our skydiving app:
- N+1 Safe Queries: We'll use
selectinload
in SQLAlchemy to avoid N+1 queries. This ensures that we're not making unnecessary database queries, which can significantly improve performance. - Database Indexes: We'll create indexes on
session_blocks(date, start_time)
,assignments(session_block_id)
, andavailability(user_id, day_of_week)
. Indexes can dramatically speed up database queries. - Pagination: We'll paginate lists to avoid loading large amounts of data at once. This is especially important for tables with a large number of rows.
By implementing these performance optimizations, we can ensure that our application is responsive and efficient. Now, let's look at how we'll set up our development environment and run the application.
Dev and Run
Setting up a consistent development environment is crucial for ensuring that everyone on the team can work effectively. We'll be using Docker and docker-compose to create a reproducible development environment. Here’s how we'll set up our development environment:
- Docker Compose: We'll use
docker-compose up --build
to start Postgres, the backend on port 8000, and the frontend on port 5173. This command builds the Docker images and starts the containers, setting up our development environment in one step. - Database Migrations: We'll use
make migrate
oralembic upgrade head
to run database migrations. This ensures that our database schema is up-to-date. - Backend Tests: We'll run backend tests using
pytest -q
. This command runs the tests in quiet mode, providing a concise output. - Frontend Tests: We'll run frontend tests using
pnpm test
. This command runs the unit tests for the frontend. - End-to-End (E2E) Tests: We'll run E2E tests using
pnpm exec playwright test
. This command runs the E2E tests using Playwright, ensuring that the application works as expected from end to end.
Using Docker and docker-compose allows us to create a consistent and reproducible development environment, making it easier to develop, test, and deploy our application. Finally, let's discuss the acceptance criteria for our project.
Acceptance Criteria
To ensure that our skydiving app meets the required standards, we'll define clear acceptance criteria for both the backend and frontend. These criteria will serve as a checklist, ensuring that we've implemented all the necessary features and that the application functions correctly. Here are the acceptance criteria for our project:
Backend
- OpenAPI Validation: The OpenAPI schema must pass validation, ensuring that our API is well-defined.
- Endpoint Implementation: All endpoints must be implemented and secured by role, ensuring that only authorized users can access certain parts of the application.
- Matching Job: The matching job must produce assignments with a target ratio of 2:1 and respect all constraints, ensuring that mentors and mentees are paired fairly and efficiently.
- Reflow After Decline: The reflow mechanism after a mentor declines an assignment must work correctly and preserve fairness, ensuring that mentees are re-assigned to suitable mentors.
- Unit Coverage: The unit test coverage for
services.matching
must be at 90 percent lines, ensuring that our matching logic is thoroughly tested.
Frontend
- Mentor Availability: Mentors must be able to create recurring availability and confirm or decline assignments, ensuring that mentors can manage their schedules effectively.
- Mentee Assignments: Mentees must be able to choose days, see assignments, and complete steps with evidence URLs, allowing mentees to track their progress and manage their sessions.
- Admin Functionality: Admins must be able to run matching, preview, publish, and download a manifest CSV, ensuring that admins can manage the system effectively.
- Progression Board: The progression board must show at least 12 steps, progress state, and badges, providing a clear view of mentees' progress.
End-to-End (E2E) Flows
We'll also define some E2E flows to ensure that the application works correctly from end to end:
- Admin Seeds Data: An admin seeds data and materializes sessions for a weekend.
- Mentor Availability and Mentee Attendance: Three mentors publish availability, and eight mentees mark attendance.
- Matching and Reflow: Matching runs, creates pending assignments, mentors confirm, one declines, and reflow assigns a waitlisted mentee.
- Post-Jump Signoffs and Awards: After jump day, mentors sign off two steps per mentee, and badges are awarded when criteria are met.
Deliverables
To complete this project, we'll deliver the following:
- Git Repository: A Git repository with the backend, frontend, Docker configurations, tests, and seed script.
- README: A README file with setup instructions, environment variables, and demo accounts (e.g., mentor:
[email protected]
, mentee:[email protected]
, admin:[email protected]
). - API Documentation: A Postman collection or
.http
files for all endpoints. - Demo: Screenshots or short loom-style GIFs of the 4 main flows.
By meeting these acceptance criteria, we can ensure that our skydiving app is a robust, user-friendly, and valuable tool for skydiving training centers.
Conclusion
Building a skydiving mentor-mentee scheduler and progression app is an ambitious project, but it's also an incredibly rewarding one. We've covered a lot of ground, from defining the project goals and tech stack to outlining the data model, matching logic, and frontend requirements. By following this roadmap and adhering to the acceptance criteria, we can create a full-stack application that solves a real-world problem and enhances the skydiving training experience. So, let's get to work and make this epic app a reality!