andyperlitch / tcf-client

0 stars 0 forks source link

TheCasualFunk.com UI

Netlify Status

Front-end code for thecasualfunk.com.

Initial Setup

Prerequisites

One-time setup

  1. Ensure correct node version is being used:
nvm use
  1. Ensure you have corepack enabled. This adds pnpm, yarn, and a few other package managers to the path:
corepack enable
  1. Install dependencies:

This project uses pnpm as the package manager. Server uses yarn.

pnpm install

Running the app locally

You will first need to start the backend API locally. See the readme there for more details.

Once that is running, you can start the front-end locally with:

pnpm dev --host

The --host flag is optional, but recommended if you want to access the app from other devices on the same network, which is a common scenario for this app.

Basic Site Structure

This app has a few basic pages:

Events and Engagements

The basic idea of this app is to have "Events" which contain multiple "Engagements". These engagements are what the audience will see and interact with. At any given time, there is one active engagement for an event. Which engagement is active is managed on the admin pages (e.g. /admin/events/funksgiving).

There are different types of engagements, and more will be added over time. The type determines what the audience will see and how they can interact with it.

One engagement type is "Photo Carousel". This is a simple engagement where the audience submits photos, which are then displayed as polaroids falling onto the stage screen.

Another is "Vote For", where the admin pre-configures a list of submissions and the audience votes for their favorite. This could also be considered a "poll" engagement.

Future ideas of engagements include:

Submissions and Reactions

Submissions are a generic concept/model that can be used by an engagement type. For example, in the "Photo Carousel" engagement type, submissions represent the photos submitted by the audience. In the "Vote For" engagement type, submissions represent the voting options, and in this case, audience members don't create submissions; only the admin does beforehand.

Submissions have a "data" property which can contain arbitrary data. For example, in the "Photo Carousel" engagement type, the data is the photo URL and a caption. In the "Vote For" engagement type, the data is the vote option text and a photo URL.

Reactions are similar to submissions, but they are a simpler model. They are used by the "Vote For" engagement type to represent the votes themselves.

Creating a new engagement type

  1. Follow the instructions in the server's readme to add your new engagement type.

  2. Create a new folder under src/engagements/, e.g. src/engagements/raffle.

  3. Inside this folder, create a file called schema.ts. This is where you will define the 5 GraphQL fragments for this engagement type's config, data, submission, and admin config data field types:

import { gql } from "@apollo/client";

gql`
  fragment RaffleAdminConfigFields on RaffleAdminConfig {
    # ...
  }
  fragment RaffleViewConfigFields on RaffleViewConfig {
    # ...
  }
  fragment RaffleAdminDataFields on RaffleAdminData {
    # ...
  }
  fragment RaffleViewDataFields on RaffleViewData {
    # ...
  }
  fragment RaffleSubmissionFields on RaffleSubmissionData {
    # ...
  }
`;
  1. Spread the fragments into the following files accordingly:
  1. Create a folder called fan inside your new engagement folder, and create a view file that will be used to render the fan-facing part of the engagement. It should accept a prop of engagement which will be the fan-facing data for the engagement. For example, assuming the name of your engagement is RAFFLE, it might be FanRaffleEngagement.tsx:
export function FanRaffleEngagement({
  engagement,
}: {
  engagement: FanEngagementFragment;
}) {
  return <div>Raffle screen!</div>;
}
  1. Create a folder called stage inside your new engagement folder, and create a view file that will be used to render the stage-facing part of the engagement. It should accept a prop of engagement which will be the stage-facing data for the engagement. For example, assuming the name of your engagement is RAFFLE, it might be StageRaffleEngagement.tsx:
export function StageRaffleEngagement({
  engagement,
}: {
  engagement: StageEngagementFragment;
}) {
  return <div>Raffle stage screen!</div>;
}
  1. Create a file called definition.tsx inside your new engagement folder. This is where you will define the engagement's definition:
import {
  EngagementType,
  RaffleAdminConfig,
  RaffleAdminData,
} from "@/gql/graphql";
import { StageRaffleEngagement } from "./stage/StageRaffleEngagement";
import { FanRaffleEngagement } from "./fan/FanRaffleEngagement";
import { EngagementDefinition } from "../base/EngagementDefinition";
import { CameraIcon } from "@radix-ui/react-icons";

export const raffleEngagementDefinition: EngagementDefinition<
  RaffleAdminConfig,
  RaffleAdminData
> = {
  title: "Raffle",
  icon: <CameraIcon />,
  type: EngagementType.Raffle,
  stageComponent: StageRaffleEngagement,
  fanComponent: FanRaffleEngagement,
  submissionsName: "Photos",
  getInitialData: () => ({
    // initial default data
  }),
  getInitialConfig: () => ({
    // initial default config
  }),
};
  1. Add your new engagement definition to the engagementDefinitionsArray array in src/engagements/index.ts.