Program setup

A React block (a whole screen) in Beamline's Salon & fitness app.

A training program's setup and living settings: the intake (one question per step, the week drawn as you answer, a failed generation keeping every answer), the program's answers changed one at a time with the week redrawn and Restart apart; limitations reported (description and areas, the app's follow-ups, a proposal of each exercise that leaves and what takes its place, nothing applied before Update plan) and removed (only their own changes); and workout preferences (the default rest set on the rest's own bar, totals recalculated by the app before they show, a setting the browser can't honour said).

Use it for

  • Setting up and adjusting a training program: the intake questions, changing an answer later, an injury or limitation that changes the plan, workout preferences.
  • Any plan made from a few answers that a person later adjusts around a constraint (rehab, study or practice plans).

Not for

Anatomy

  • rail: Program, Limitations (its count), Preferences; on a phone a row above the view
  • intake (no program yet): step-form on its card, one question per step; beside it 'Your week' taking shape: seven open days until the days are chosen, then a column per day with a bar of quarter-hours as long as the session (a length not chosen yet hatched), and under it the answers so far (set in ink, not yet a dash)
  • program: its title and week; the answers as rows, each with Change (the question in place, Save or Cancel; the week redraws while days or length change); 'Your week' large (each day's title and minutes, rest days said); Restart program apart, asked in place
  • limitations: the active ones as cards (area, date reported, what it took out and what it put in, Remove asked in place) beside the Report card (what's wrong and where, the app's follow-ups, the proposal with Update plan or Start over); under them across the width 'Your week, around it': seven days (rest days narrow), each session's exercises as tiles with every swap in place (instead of …) and a proposal's swaps drawn before Update plan (leaving struck, the replacement ringed); a list of training days on a phone
  • preferences: the settings as a list (rest timer, its sound, where previous values come from, warm-ups counted with the totals, keep the screen awake or what the browser can't, record alerts) beside 'A set as you'll log it' (with preview): the previous line from the chosen source, the set rows (target-table), what the set counts as with or without warm-ups, the rest (the timer's bar sets the default rest), and a line for the sound, the screen and a new best, each following its setting

States

  • intake: unanswered, a step that needs an answer, generating, generation failed (reason above the actions, every answer kept)
  • program: changing an answer, saving, not saved (said in the row), restart asking, restarted
  • limitations: none, active, removing asked, removal refused (stays, reason said), reporting: describing, reading, follow-ups, working out, proposal, updating, not updated (draft and proposal kept, Try again), applied
  • preferences: rest off, rest dragged, saving, not saved (the setting goes back, reason said), recalculating totals (until the app returns them), the browser can't keep the screen awake
  • narrow room: the rail as a row, one column

Keyboard

  • the rail: Tab and Enter
  • the intake's controls as step-form's (cards and chips by arrows, the slider by arrows)
  • the rest's bar: ←/→ by 15 s (Shift: more), as the timer's
  • Remove and Restart ask in place (Escape cancels)

Motion

The week's bars grow to a new length on the motion tokens; nothing moves at rest; reduced motion places at once.

Props

PropTypeDefaultDescription
equipment / muscles / areas (required)string[]—equipment: Equipment the intake offers, in your app's words. muscles: Muscles the focus question offers. areas: Areas a limitation can be in ("Knee", "Lower back").
program / defaultProgram / onProgramChangeProgramPlan | null—The current program; null shows the intake.
answers / defaultAnswers / onAnswersChangeProgramAnswers—The intake's answers.
onGenerate (required)(answers) => Promise<ProgramPlan>—Makes the program from the answers. Reject with an Error: its message shows and every answer stays.
onUpdateAnswers / onRestart(answers) => Promise<ProgramPlan> / () => Promise<ProgramPlan>—onUpdateAnswers: Saves a changed answer; resolve with the program as it now is. onRestart: Starts the program again from week 1.
limitations / defaultLimitations / onLimitationsChangeLimitation[]—The active limitations with the changes each made.
onAskFollowUps / onPropose / onApplyLimitation / onRemoveLimitation (required)Promise-returning—onAskFollowUps: Reads a new limitation's description and areas; resolve with the questions to ask (none is fine). onPropose: Works out the changes; nothing applies yet. onApplyLimitation: Applies the proposal (Update plan); resolve with the stored limitation. Reject: the draft stays. onRemoveLimitation: Removes a limitation and only its own changes. Reject: it stays active, with the reason said.
preferences / defaultPreferences / onSavePreferencesWorkoutPreferences—Saved on each change; resolve with new totals when they depend on it.
totalsTrainingTotals | null—The totals as the app last computed them.
canKeepAwakeboolean—The browser can keep the screen awake (the Screen Wake Lock API). Default: detected.
view / defaultView / onViewChange"program" | "limitations" | "preferences"—The view in the rail.
equipment (required)string[]—Equipment the intake offers, in your app's words.
muscles (required)string[]—Muscles the focus question offers.
areas (required)string[]—Areas a limitation can be in ("Knee", "Lower back").
programProgramPlan | null—The current program; null before the intake (the Program view is then the intake).
defaultProgramProgramPlan | null—
onProgramChange((program: ProgramPlan | null) => void)—
answersProgramAnswers—
defaultAnswersProgramAnswers—
onAnswersChange((answers: ProgramAnswers) => void)—
onUpdateAnswers((answers: ProgramAnswers) => Promise<ProgramPlan>)—Saves a changed answer; resolve with the program as it now is.
onRestart(() => Promise<ProgramPlan>)—Starts the program again from week 1.
limitationsLimitation[]—
defaultLimitationsLimitation[]—
onLimitationsChange((limitations: Limitation[]) => void)—
onAskFollowUps (required)(draft: LimitationDraft) => Promise<FollowUp[]>—Reads a new limitation's description and areas; resolve with the questions to ask (none is fine).
onPropose (required)(draft: LimitationDraft) => Promise<LimitationProposal>—Works out the changes; nothing applies yet.
onApplyLimitation (required)(draft: LimitationDraft, proposal: LimitationProposal) => Promise<Limitation>—Applies the proposal (Update plan); resolve with the stored limitation. Reject: the draft stays.
onRemoveLimitation (required)(id: string) => Promise<void>—Removes a limitation and only its own changes. Reject: it stays active, with the reason said.
preferencesWorkoutPreferences—
defaultPreferencesWorkoutPreferences—
onSavePreferences (required)(preferences: WorkoutPreferences) => Promise<void | TrainingTotals>—Saves preferences; resolve with new totals when they depend on the change (warm-ups counted). Reject: the setting goes back, the reason said.
viewSetupView—
defaultViewSetupView—
onViewChange((view: SetupView) => void)—
weekStartsOn0 | 1—First day of the week in "Your week": 0 Sunday, 1 Monday. Default 1.
labelsPartial<{ setup: Message; view_program: Message; view_limitations: Message; view_prefer…—
classNamestring—Classes on the documented visual root; no override by default.
refRef<HTMLDivElement>—Receives the documented native target or imperative handle; omitted by default.
previewPreferencesPreview—A set from the person's own log for Preferences to show each setting's effect on: its rows, and where "previous" would come from. Without it Preferences is the settings alone.

Built from

Dependencies

lucide-react

Import

import { ProgramSetup, NO_ANSWERS } from "@beamline/program-setup";

Get it

Program setup is part of Beamline UI. Install the parts you need in your React app as compiled packages or editable source. Get Beamline · Connect your agent

More in Salon & fitness

  • Workout planner: A training plan a person lives in: the program's next session with its estimate and Start, an exercise replaced for this session only or for every later…
  • Workout logger: A live training session: every exercise's sets as target-table rows with a done column; marking a set done fills its shape and starts the rest by itself…
  • Training progress: A person's training history: the headline counts (weeks in a row, days since the last workout, workouts this month), a month calendar that names each…
  • Protocol builder: A practitioner's reusable protocol and the client copies made from it. Foods and habits each carry a written intent (Include, Reduce, Exclude) in its…
  • Nutrition library: A nutrition practice's library. Recipes: ingredients with grams and servings, nutrients per serving summed (energy, protein, carbohydrate, fat, fibre), a…
  • Packages & memberships: Prepaid packages and series, built: the packages down the side (version and how many sold, or not on sale yet), the open one beside them. Its price is a…
  • Client forms: A salon's or spa's client forms and who they ask: the forms down the side with where each stands (on, set up and off, not set up yet), the open one…
  • Instructor finder: Finding a flight instructor. Search by name or airfield, filter by what you want to learn (each subject with how many teach it nearby), by distance, and…
  • Flight logbook: A pilot's logbook. Total time (with hours brought forward from earlier logbooks), PIC, night, the last 90 days and how many entries are still incomplete…

Part of Beamline UI: polished, editable React components and complete screens for custom applications. Build your own style from any look; tokens, fonts, radii, motion; not only colours.