Skip to content

Create your own watch schedule for shows and movies! Define layers of shows and movies, with each layer watched in order, and all layers watched simultaneously. Select start and end points for shows, so you can schedule a specific range. Bookmark your progress, seeing completion percentages. Add custom entries for books and more. + Other features!

Notifications You must be signed in to change notification settings

Hoffee-Toffee/SeriesMingle

Repository files navigation

SeriesMingle

Live-Site

This is the documentation for the SeriesMingle Repository.

Work in Progress

File Structure

Test Status Key:

Status Symbol Usage
Test Passed βœ… Test passes for case
Test Failed πŸ›‘ Test fails for case
Future Test 🚧 Test not yet implemented

Route Protection Key:

Status Symbol Usage
Protected Route βœ… Authentication required
Public Route ❎ No authentication required
To be Protected πŸ›‘ Authentication planned
Future Route 🚧 Route not yet implemented

/client/apis

Contains all API functions.
Each file contains and (default) exports a function that makes a request to the server.
Unless otherwise stated, all functions return the body of the response.

Clones a project of a given id, if the user has access to it, assigning the clone to the user.

To be updated into using auth from logged in user, instead of passing user id.

Params:

Parameter Data Type Description
id string The id of the project to clone
user string The user id of the user to own the cloned project

Endpoint: POST /api/v1/projects/clone

// Request Body
{
  "id": "iasIFGOcdOlRZvYNNB4a",
  "user": "5feNQ3XPKZRnpaMydanS8C1OZcs2"
}

Tests:

Case Expected Output Test Status
ID is of project user owns Success 🚧
ID is of project user has been invited to Success 🚧
ID is of project user does not have access to Failure 🚧
ID is invalid Failure 🚧
User is not authenticated Failure 🚧

Creates a new project and assigns it to the user.

To be updated into using auth from logged in user, instead of passing user id.

Params:

Parameter Data Type Description
user string The user id of the user to own the new project

Endpoint: POST /api/v1/projects/create

// Request Body
{
  "user": "5feNQ3XPKZRnpaMydanS8C1OZcs2"
}

Tests:

Case Expected Output Test Status
User is authenticated Success 🚧
User is not authenticated Failure 🚧

- deleteProject.ts

Deletes a project of a given id, if the user owns it.

To be updated into using auth from logged in user.

Params:

Parameter Data Type Description
id string The id of the project to delete

Endpoint: GET /api/v1/projects/delete/:id

Returns a status code.

Tests:

Case Output Case Test Status
ID is of project user owns Success 🚧
ID is of project user does not own Failure 🚧
ID is invalid Failure 🚧
User is not authenticated Failure 🚧

- fetchMedia.ts

Fetches extended details for a movie or tv show of a given id.

Params:

Parameter Data Type Description
type string The type of media to fetch ('movie' or 'tv')
id string The id of the media to fetch

Endpoint: GET /api/v1/:type?id=:id

Tests:

Case Expected Output Test Status
ID is valid Success 🚧
ID is invalid Failure 🚧
Type is valid Success 🚧
Type is invalid Failure 🚧

- fetchProject.ts

Fetches a project of a given id, if the user has access to it.

To be updated into using auth from logged in user.

Params:

Parameter Data Type Description
id string The id of the project to fetch

Endpoint: GET /api/v1/projects/:id

Returns a processed project object.

To be migrated

Tests:

Case Expected Output Test Status
ID is of project user owns Success 🚧
ID is of project user has been invited to Success 🚧
ID is of project user does not have access to Failure 🚧
ID is invalid Failure 🚧
User is not authenticated Failure 🚧

Fetches the decrypted content of an Easter Egg, if the passphrase is correct.

Params:

Parameter Data Type Description
passphrase string The passphrase to decrypt the content

Endpoint: GET /api/v1/secret?passphrase=:passphrase

Returns the raw text decrypted from the Easter Egg file.

Tests:

Case Expected Output Test Status
Valid passphrase Success 🚧
Invalid passphrase Failure 🚧

- fetchUserProjects.ts

Fetches all projects owned by a user.

To be updated into using auth from logged in user.

Params:

Parameter Data Type Description
user string The user id of the user to fetch projects for

Endpoint: GET /api/v1/projects/user/:user

Tests:

Case Expected Output Test Status
User is authenticated Success 🚧
User is not authenticated Failure 🚧

Removes a user from a project of a given id, if the user is a member.

To be updated into using auth from logged in user.

Params:

Parameter Data Type Description
projectId string The id of the project to leave
userId string The user id of the user to remove from the project

Endpoint: POST /api/v1/projects/leave/:projectId

// Request Body
{
  "userId": "5feNQ3XPKZRnpaMydanS8C1OZcs2"
}

Tests:

Case Expected Output Test Status
ID is of project user is a member of Success 🚧
ID is of project user is not a member of Failure 🚧
ID is invalid Failure 🚧
User is not authenticated Failure 🚧

Searches for a movie or tv show by a given query.

Params:

Parameter Data Type Description
query string The search query to search for

Endpoint: GET /api/v1/search?q=:query

Returns an array of search results, with the query added to the front of the array.

To be migrated.

Tests:

Case Expected Output Test Status
Query is valid Success 🚧
Query is invalid Failure 🚧

Sets a project of a given id, to the given data, if the user has access to it.

To be updated into using auth from logged in user.

Params:

Parameter Data Type Description
state object The new project data
id string The id of the project to set
props string[] The properties that have been changed

Endpoint: POST /api/v1/projects

// Request Body
{
  "id": "iasIFGOcdOlRZvYNNB4a",
  // ...state (Spread of new project data)
  "props": ["description"],
  "layers": // Conversion from an array to an object with layer indices as keys
}

Tests:

Case Expected Output Test Status
ID is of project user owns Success 🚧
ID is of project user has been invited to Success 🚧
ID is of project user does not have access to Failure 🚧
ID is invalid Failure 🚧
User is not authenticated Failure 🚧

/client/components

Contains all React components.
Each file contains and (default) exports a React component.
Any documented state `xyz` has an undocumented setter named `setXyz`.

Root component for the application.

Styled with app.scss.

Props: None

Data:

Data Source Type (default value) Description
location useLocation().key string Identifier for the current page
user State auth.currentUser The current user, or null if not logged in
isAuthLoaded State boolean (false) Whether the authentication state has been loaded
isPageLoaded State boolean (false) Whether the page has been loaded
showLoading State boolean (false) Whether the loading screen should be shown
hasLoaded const boolean (isAuthLoaded && isPageLoaded) Whether all page data has been loaded
loader const setTimeout Starts a loading screen if page has not loaded after 2 seconds
page const string ("home") uses useOutlet() to get the current page name

Effects:

Dependencies Description
loader, showLoading, auth.onAuthStateChanged Sets user and isAuthLoaded when authentication state changes, and clears a loading screen if it is shown
location Resets isPageLoaded to false when entering a new page
useScroll(isPageLoaded) from scroll.ts Adds a scroll listener, if applicable, when the page has loaded

Returns:

Uses `Helmet` to set the page title, favicon, and meta tags.
Shows a loading indicator, with `hasLoaded` being used to toggle it's class.
If authenticated, then user and loading providers are added, containing a div with an id of the page name, containing the outlet component.

`UserContext` and `LoadingContext` are exported for use in child components.

Tests: None

Component for the 404 page.

Very basic containing only text.

Component for the home page.

Styled with home.scss.

Props: None

Data:

Data Source Type (default value) Description
user Context (UserContext from App.tsx) User The current user, used to determine if the user is logged in
isPageLoaded Context (LoadingContext from App.tsx) boolean Whether the page has loaded

Effects:

Dependencies Description
isPageLoaded, setIsPageLoaded Sets the page to loaded

Returns:

Header containing the SeriesMingle logo and nav menu with links to 'About', 'Upcoming Features', and either 'Login or Register' or 'Dashboard' depending on if the user is logged in.

The main section contains several headers with features listed, showing an example behind each.
'Get Started' / 'Go to Dashboard' button at the bottom of each.

Upcoming features section has a list of planned features, no example or button.

Each section has a scroll indicator, except the last, which prompts the user to get started.

Tests: None

Component showing example project actions for the home page.

Styled with home.scss and project.scss.

Props:

Prop Type Description
id string The id to give the example element

Data: None

Returns:

A pre-rendered schedule containing two layers:
- Breaking Bad (All Episodes), El Camino, and Better Call Saul (All Episodes)
- House (All Episodes)

In future, I plan to add a third layer containing a long movie series (e.g. James Bond).

For notes on schedule generation, see [generateSchedule.ts](#--generateschedulets).

Tests: None

Component for the login page.

Styled with login.scss.

Props: None

Data:

Data Source Type (default value) Description
user Context (UserContext from App.tsx) User The current user
error State string ("") The error message to display
creatingEmail State boolean (false) Whether the user is creating an account, or logging in
emailRef Ref HTMLInputElement The email input element
passwordRef Ref HTMLInputElement The password input element
confirmPasswordRef Ref HTMLInputElement The confirm password input element
isPageLoaded Context (LoadingContext from App.tsx) boolean Whether the page has loaded
onSubmit function Handles form submission, creating or logging in the user, and displaying errors
SignInWithGoogle function Activates Google's sign in popup, and logs in the user (if successful)

Effects: None

Returns:

Simple form with:
- SeriesMingle logo / heading
- Email input
- Password input (and confirm password input if creating an account)
- Submit button
- Sign in with Google button
- Span with error message
- Link to toggle form between login and create account configurations

User is redirected to the dashboard if they are logged in.
If user was redirected here from a protected route, they are redirected back after logging in.

Component wrapping and protecting a route.

Props:

Prop Type Description
children ReactNode The component to render if conditions are met
ifLoggedIn boolean (true) Whether the user must be logged in to access the route (i.e. dashboard only if logged in, login only if not)
redirectTo string ("/login") The route to redirect to if conditions are not met
includeRedirect boolean (false) Whether to include this route in the URL redirect (so the user can be redirected back here after logging in)

Data:

Data Source Type (default value) Description
user Context (UserContext from App.tsx) User The current user
searchParams useSearchParams() URLSearchParams The search parameters of the current URL
from searchParams.get("from") string The route the user was redirected from

Returns:

If includeRedirect is true, then redirectTo is given the current route as a search parameter (?from=...).
If not, and from is provided, then that is where the user is redirected to.

Finally, if the user's sign in status matches ifLoggedIn, then the children are rendered, otherwise the redirect is triggered.

Tests: None

Component for the dashboard page.

Styled with dash.scss.

Props: None

Data:

Data Source Type (default value) Description
user Context (UserContext from App.tsx) User The current user
isPageLoaded Context (LoadingContext from App.tsx) boolean Whether the page has loaded
ownedProjects State Project[] ([]) Projects owned by the user
joinedProjects State Project[] ([]) Projects the user has joined
navigate UseNavigate function Navigates to a new page
db GetFirestore function Gets the Firestore database
createProjectAndOpen async function Creates or clones a given project, and navigates to it
deleteProjectAndRemove async function Deletes a given project from ID, and removes it from the displayed projects
leaveProjectAndRemove async function Leaves a given project from ID, and removes it from the displayed projects

Effects:

Dependencies Description
user, db, setPageLoaded Fetches the user's owned and joined projects from the database, and then sets the page to loaded

Returns:

Sign Out button on the top left, which signs out the user, directing them to the home page.

Dashboard heading is displayed, with two sections:
- Owned Projects, with a project card for each owned project, and a button to create a new project.
- Joined Projects, with a project card for each joined project.

Tests: None

Used on the dashboard page to display a project card.

Styled with dash.scss.

Props:

Prop Type Description
project Project The data for the project to display
owner boolean Whether the user is the owner of the project

Data:

Data Source Type (default value) Description
contextMenu Document HTMLElement The context menu element
deletePopup Document HTMLElement The delete popup element
positionContextMenu(target) function Positions the context menu relative to the hovered card

Returns:

Project card, linking to the project page, containing:
- Project title (or 'Untitled Schedule' if none)
- Project description (or 'No Description' if none)
- Ellipsis icon, opening a context menu with options to:
  - Delete Project (if owner is true)
  - Leave Project (if owner is false)
  - Clone Project

Tests: None

Component for the project page.

Styled with project.scss.

Props: None

Data:

Data Source Type (default value) Description
user Context (UserContext from App.tsx) User The current user
isPageLoaded Context (LoadingContext from App.tsx) boolean Whether the page has loaded
readOnly State boolean (true) Whether the user can edit the project
id useParams().id string The id of the project to access
uid user.uid string The id of the current user
db GetFirestore function Gets the Firestore database
initialState Project Blank project configuration
state State Project(initialState) The current project data
activeEntry State string(null) Identifier for an entry being dragged
tempLayers State array([]) Stores temporary layers for drag and drop, to be set once dropped
outlinePos State string(null) Identifier for the projected drop position of the dragged entry
hasAccess State boolean(false) Whether the user has access to the project
changedProps State string The properties that have been changed
saved State boolean(true) Whether the local project data has been saved
sensors UseSensors function Gets the sensors for drag and drop
savedJS State object({}) Any decoded easter eggs to run
shown tempLayers || layers The layers being displayed, showing the temp if they exist, otherwise the saved project layers
addData(entry, layerId, entryId) function Adds show / movie data to the project, assigning a reference to that data in a specified layer and entry
removeWatched function Removes all entries before the bookmark in the schedule
scheduleData generateSchedule(...state) from generateSchedule.ts object The schedule generated using the project data
...state state Project All project data is spread out into their own consts for easy access
set{Prop} function Updates this value in the project data, adding it to the props changed list
onDragStart(event) function Handles the start of a drag event, setting the active entry
onDragEnd(event) function Handles the end of a drag event, setting the active entry, outline position, and temp layers to null, after setting the layers to the new order
onDragOver(event) function Handles the drag over event, setting the outline position
moveEntry(oldLayer, oldIndex, newLayer, newIndex) function Moves an entry from one layer to another, or within the same layer, used in onDragEnd

Effects:

Dependencies Description
saved If project hasn't saved, use a beforeunload listener to warn the user
id, uid, db, setPageLoaded Fetches the project data from the database, and sets the page to loaded, listening for changes to the project data
keys, savedJS Saves and runs any decoded easter eggs
bookmark If the user has a bookmark, scroll to it
...state If the project data changes, update the project data in the database

Returns:

If it has loaded, but you have no access, then it returns only "No Access" text.

If readonly, then you see 'READ-ONLY' at the top and all db calls are disabled.

In the top-left corner you will see some buttons:
- Back to Dashboard
- Share Schedule (if layers are not empty)
- Load Example (if layers are empty, sets the project to the example project)

At the top we see the title and description of the project.
This text is editable if the user has access.

There is then a layer container, with drag and drop contexts surrounding it.
The Layer component is rendered for each layer, with the layer data passed down.
After all the layers is a button to add a new layer.
And there is also one Entry component here, shown only during drag and drop, to follow the mouse as the user drags an entry.

Next are the schedule settings, including:
- Space Multi-Parters (Radio buttons: 'Normally', 'Closer', and 'Consecutively')
- Streak Duration (Number input, or blank if not set)
- Streaks per Session (Number input, or blank if not set, only shown if Streak Duration is set)
- Session duration (Number input, or blank if not set, only shown if Streak Duration is not set)
- Show Streaks (Checkbox, only shown if Streaks or Sessions exist)
- Group Streaks (Checkbox, only shown if Streaks or Sessions exist)

Finally, the schedule component is rendered, with the schedule data and user props passed down.

Tests: None

About

Create your own watch schedule for shows and movies! Define layers of shows and movies, with each layer watched in order, and all layers watched simultaneously. Select start and end points for shows, so you can schedule a specific range. Bookmark your progress, seeing completion percentages. Add custom entries for books and more. + Other features!

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published