Skip to content

Many things - #358

Merged
gregv merged 30 commits into
mainfrom
develop
Sep 1, 2026
Merged

Many things#358
gregv merged 30 commits into
mainfrom
develop

Conversation

@gregv

@gregv gregv commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

No description provided.

gregv and others added 30 commits August 17, 2026 20:22
Judges must complete the two-video "Opportunity Hack Judging" bundle on
lms.ohack.dev (Judge Intro + Using the judging tool) before the form
unlocks. JudgeTrainingGate renders instead of the stepper/form until
both certificate links verify live against the LMS's public
certificate-verification query; links persist in formData, hydrate for
returning judges, submit with the application, and show as links in
admin review.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lms.ohack.dev signs in through the same PropelAuth instance as
www.ohack.dev, and its Convex deployment trusts that issuer. The gate
now calls the LMS with the judge's own access token (ensureExternalUser
then getMyCertificates), fills the certificate fields itself, and
re-checks on tab refocus and via an explicit "check again" button — no
copy/paste needed. Manual paste stays as the fallback (different
account, dev issuer mismatch, LMS unreachable). Verified values are
never overwritten by auto-detect.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ing-gate

Judge application: hard-gate behind LMS training certificates
…deas

The review table crammed 10 raw-field columns into equal widths, leaving
the Idea column — the one thing reviewers read — smushed to ~150px.

- Merge legacy duplicate fields per row (name/contactName,
  organization/charityName, idea/technicalProblem) down to 4 columns so
  Idea gets ~46% of the table as a 3-line-clamped reading block
- "Show more" expands long ideas in place; extra fields (technical
  problem, solution benefits, notes) open in a full-width reading panel
- Organization cell carries the nonprofit-status dot; Contact cell links
  mailto; Submitted shows date + relative age
- Search now also matches idea/notes text; result count shown; sort uses
  merged-field accessors and no longer mutates state in place
- Drop the response console.log (application payloads carry PII)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the hacker form's free-text dietary field with a shared
DietaryRestrictionsSelect (multi-select of common restrictions +
"Other" detail, "None" exclusive) and add the question to the mentor,
judge, and volunteer forms — shown only at physical events when the
applicant answers they'll attend in person, since meals are only
served on site.

The stored value stays a human-readable comma-joined string (legacy
free-text submissions parse into the picker), so it flows through the
existing submit/update endpoints with no backend change. Surfaced in
admin review (ApplicationReviewCard) and edit (ApplicationEditDialog)
for all four types.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tions-dropdown

Dietary restrictions: shared dropdown on hacker, mentor, judge, and volunteer applications
…-application-review

Admin nonprofit applications: readable review table with expandable ideas
…tion

Adds constraints.meals_mode ("menu" default | "schedule") and an optional
constraints.meals_note. In schedule mode the admin Meals section becomes a
minimal name+time editor (items/catalog/cost UI hidden, item data kept) and
the hacker application renders the new read-only MealSchedule instead of the
MealMenu pickers. formatMealTime now renders admin-picked ISO times
human-readably in both components. Unit tests for the helpers, the schedule
component, and the hacker-form gating.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…teers

The read-only MealSchedule now renders on the mentor, judge, and volunteer
applications directly above DietaryRestrictionsSelect, under the same gate
that PR #349 established for dietary restrictions (!isVirtualEvent() and an
in-person "Yes!"/"Yes" answer). These roles never pick menu items, so the
schedule shows regardless of meals_mode. Mentor + volunteer setEventData now
retain constraints (judge already did); the component owns the no-meals case.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…only-mode

Meals: times-only mode — publish meal times without hacker item selection
Sync the "up to 14 business days, we're volunteers too" pending-review
copy across the judge, mentor, and volunteer application forms
(pre-submit notice + post-submit success screen), matching the wording
already updated on the judge form.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Every application edit was sending isSelected: false from the form's
initial state (sponsor hardcoded it in the payload), which the backend
used to honor — silently un-approving approved mentors, judges,
volunteers, and sponsors on every update.

- Remove isSelected from initialFormData in mentor/volunteer/sponsor/
  hacker forms, the hardcoded payload field in sponsor, and the
  hydration round-trip in hacker.
- Remove judge's vestigial `selected` form field and its dead hidden
  input (the form submits via fetch, not native POST).
- Approval is now server-authoritative: the backend strips staff-owned
  fields from self-service submits (backend PR pairs with this).

The isSelected React state used for UI gating (QR cards, feedback CTA)
is a separate variable and is untouched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rop-isselected

Stop application forms from sending isSelected (approval reset bug)
Public /jobs index and /jobs/[slug] detail pages (ISR, refined design,
JobPosting schema with employmentType VOLUNTEER for Google for Jobs).
Login-gated 4-step application form with required work sample, PDF
resume upload, and intro video. /admin/jobs manages listings and
reviews applications with one-click accept/kind-rejection emails.
Sitemaps, admin nav registration, and a /volunteer cross-link included.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a Volunteer Jobs item to the Get Involved dropdown, an organizer-jobs
button on the /about final CTA, and a line in the onboarding roles step.
Also renames the 'As long as I'm useful' duration option to
'Ongoing — I'd love to stick around'.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Link /jobs from NavBar, /about, and onboarding
- Extract the LMS Convex transport from JudgeTrainingGate into a shared
  src/lib/lmsClient.js (gate's public exports unchanged) and add
  use-judge-training-status: anonymous cert verification for every admin
  plus an authed attempts rollup (listQuizzes/getQuizResults/listUsers)
  when the admin's LMS account has an admin/editor role, joined to judge
  applications by email behind a 60s cache with one batched setState.
- VolunteerWorkbench hosts the single fetch (Judges tab only) and one
  page-level VideoDisplay dialog shared by the table and review views.
- ApplicationReviewCard gains a judge-only JudgeTrainingPanel (video
  thumbnail, per-quiz verification rows with score/issue date/attempts,
  judgeTrainingCompleted chip); VolunteerTable gains judges-only
  Training and Video columns with a detail tooltip and mobile-card chip.
- Fix a pre-existing card bug where links rendered as plain text when
  expanded (missing isLink arg) and hoist the 3 duplicated isLink
  arrays into one LINK_FIELDS constant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ining-review

Admin judge review: inline intro-video player + LMS training status
… inactive-Slack toggle

- /admin/communication now has three tabs (templates | email | social); the
  Email Communication UI is extracted from SocialMediaManagement into
  EmailCommunication.js and no longer blocks on social credential validation
- Slack picker defaults to active_days=365 with an "Include inactive
  accounts" toggle (deleted/disabled accounts stay excluded server-side)
- Broadcast mode: source picker (registered users / leads / Slack / event
  volunteers / contact_submissions by inquiry type / pasted emails), preview
  counts, standing-segment sync with polled progress, compose with
  placeholder lint, draft/send/schedule, status panel, and a contact
  manager with quota bar + prune actions (unsubscribed / selected / all)
- Mass personalized sends now go through the backend Resend Batch endpoint
  in chunks of 100 (email-only recipients; QR messages and registered users
  keep the per-recipient path, incl. its Slack DM side effect)
- Fix: Slack-sourced recipients were misrouted to /api/admin/{slackId}/message
- Fix: BatchEmailDialog toasts were silently swallowed (no SnackbarProvider);
  it now accepts the page's onSnack

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…asts

Admin Email tab: Resend broadcasts + batched sends, inactive-Slack toggle, contact manager
The judge photo was an optional bare label/button tucked under the intro
video card and applicants were skipping it. It now sits in its own
--surface-2 panel with copy that states the photo is public (DevPost +
ohack.dev), in deliberate contrast to the video's review-team-only note,
and validateBackgroundAndExperience blocks step-Next/submit when neither
formData.photoUrl nor uploadedPhotoUrlRef is set.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Judge application: require a public photo, frame it so it isn't missed
INQUIRY_TYPES carried a second "other" entry (duplicate MenuItem + React
key warning) and a legacy "prize" type superseded by claim_reward. Both
removed. Nonprofit inquiries now link to /nonprofits/apply. Selecting
Mentor or Judge in the dropdown opens a confirmation dialog pointing at
/about/mentors or /about/judges before the type is applied; deep links
(?type=) and the quick-select chips bypass it. Drops four unused MUI
imports.

Recovered from a May 2026 stash (team-completion-checklist branch) that
never landed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Contact page: dedupe inquiry types, guide-first prompt for mentor/judge
@vercel

vercel Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
frontend-ohack-dev Building Building Preview Sep 1, 2026 11:37pm UTC

Request Review

@gregv
gregv merged commit 5be06cd into main Sep 1, 2026
2 of 3 checks passed
const parsed = new URL(value);
return (
(parsed.protocol === "https:" || parsed.protocol === "http:") &&
parsed.hostname.toLowerCase().includes("linkedin.com")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants