Skip to content

Add prerequisites field for workshop proposals#342

Merged
Starefossen merged 6 commits intomainfrom
copilot/add-prerequisites-section
Feb 16, 2026
Merged

Add prerequisites field for workshop proposals#342
Starefossen merged 6 commits intomainfrom
copilot/add-prerequisites-section

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 16, 2026

Implementation Plan: Workshop Prerequisites Field

  • Explore codebase structure for proposals, workshops, and forms
  • Add prerequisites field to Sanity schema (talk.ts)
  • Update TypeScript types in proposal/types.ts
  • Update validation schemas in server/schemas/proposal.ts
  • Update ProposalDetailsForm component to include prerequisites input (visible only for workshops)
  • Display prerequisites on TalkCard component (for workshops)
  • Test the implementation (form submission, display, validation)
  • Run code quality checks (lint, typecheck, tests)
  • Request code review (no issues found)
  • Run security checks (no vulnerabilities found)
  • Address Qodo code review feedback:
    • Add backend validation to ensure prerequisites only for workshops
    • Normalize empty/whitespace strings to undefined
    • Clear prerequisites when format changes to non-workshop
    • Add comprehensive tests for all scenarios

Summary

Successfully implemented a prerequisites field for workshops with all quality checks passing and code review feedback addressed.

Latest Changes (Qodo Review)

Backend Validation: Added .refine() check to reject prerequisites on non-workshop formats
Data Normalization: Trim and transform empty/whitespace-only strings to undefined
Format Change Handling: Clear prerequisites when switching from workshop to non-workshop format
Comprehensive Tests: Added 3 new tests covering all edge cases

Code Quality Results

  • ✅ TypeScript compilation: PASSED
  • ✅ ESLint linting: PASSED
  • ✅ Prettier formatting: PASSED
  • ✅ Tests: PASSED (1,536 tests, including 5 new tests for prerequisites)
  • ✅ Code review: ALL ISSUES ADDRESSED
  • ✅ Security scan (CodeQL): NO VULNERABILITIES
Original prompt

This section details on the original issue you should resolve

<issue_title>Add a prerequisites section for workshops</issue_title>
<issue_description>Description

Workshops often come with prerequisites e.g. "bring a computer with Docker installed". For now, it's possible to add this info to the abstract section, but having it as a separate field reminds the workshop speaker to add it, and makes it easier to display on talk pages.</issue_description>

<agent_instructions>Speakers should be able to specify prerequisites for workshops.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.


PR Type

Enhancement, Tests


Description

  • Add prerequisites field for workshop proposals in schema and types

  • Implement conditional form input with helper text for workshops only

  • Display prerequisites in highlighted box on confirmed workshop cards

  • Add validation tests for prerequisites field handling


Diagram Walkthrough

flowchart LR
  A["Workshop Proposal"] -->|"Add prerequisites field"| B["Schema & Types"]
  B -->|"Conditional visibility"| C["ProposalDetailsForm"]
  C -->|"Textarea input"| D["Form Submission"]
  D -->|"Validation"| E["ProposalInputSchema"]
  E -->|"Display on confirmed"| F["TalkCard"]
  F -->|"Blue highlighted box"| G["Workshop Details"]
Loading

File Walkthrough

Relevant files
Enhancement
6 files
talk.ts
Add prerequisites field to Sanity schema                                 
+17/-0   
types.ts
Add prerequisites property to Proposal interface                 
+1/-0     
proposal.ts
Add prerequisites validation to schema                                     
+1/-0     
ProposalDetailsForm.tsx
Add prerequisites textarea input for workshops                     
+34/-0   
ProposalForm.tsx
Include prerequisites in form state management                     
+1/-0     
TalkCard.tsx
Display prerequisites in blue box for workshops                   
+16/-1   
Tests
1 files
schemas.test.ts
Add tests for prerequisites field validation                         
+19/-0   

Greptile Summary

Added optional prerequisites field for workshop proposals following existing patterns. Field is conditionally visible for workshop formats (workshop_120, workshop_240) in both Sanity CMS and frontend forms. Prerequisites display in a blue-themed box below the description on confirmed workshop talk cards. Implementation includes comprehensive test coverage validating optional field behavior.

Confidence Score: 5/5

  • Safe to merge with no issues found
  • Implementation follows existing codebase patterns consistently (mirroring capacity field approach), includes comprehensive test coverage, uses proper conditional rendering with isWorkshopFormat() helper, maintains type safety throughout the stack, and adheres to project guidelines for minimal comments and clean code
  • No files require special attention

Important Files Changed

Filename Overview
sanity/schemaTypes/talk.ts Added prerequisites field to talk schema following existing capacity field pattern with conditional visibility for workshops
src/lib/proposal/types.ts Added prerequisites optional string field to Proposal interface
src/server/schemas/proposal.ts Added prerequisites field validation with nullable/optional transforms in base proposal schema
src/components/proposal/ProposalDetailsForm.tsx Added prerequisites textarea input with conditional rendering for workshop formats in both edit and read-only modes
src/components/program/TalkCard.tsx Added prerequisites display in blue-themed box for confirmed workshops between description and metadata sections
tests/lib/proposal/schemas.test.ts Added comprehensive test coverage for prerequisites field validation in workshop and non-workshop scenarios

Flowchart

flowchart TD
    A[Sanity Schema: talk.ts] -->|defines prerequisites field| B[Type Definition: types.ts]
    B -->|prerequisites?: string| C[Validation Schema: proposal.ts]
    C -->|validates input| D[ProposalDetailsForm]
    D -->|conditional rendering| E{Is Workshop Format?}
    E -->|Yes| F[Show Prerequisites Textarea]
    E -->|No| G[Hide Prerequisites Field]
    F -->|user input| H[ProposalForm]
    H -->|includes prerequisites| I[Submit to Backend]
    I -->|store in Sanity| J[TalkCard Display]
    J -->|conditional display| K{Confirmed Workshop?}
    K -->|Yes + has prerequisites| L[Show Blue Prerequisites Box]
    K -->|No| M[Hide Prerequisites]
    
    style A fill:#e1f5ff
    style B fill:#e1f5ff
    style C fill:#e1f5ff
    style D fill:#fff4e1
    style H fill:#fff4e1
    style J fill:#e8f5e9
    style L fill:#e8f5e9
Loading

Last reviewed commit: b2d7053

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 16, 2026

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

Project Deployment Actions Updated (UTC)
cloudnativedays Ready Ready Preview, Comment Feb 16, 2026 0:40am

Request Review

…splay

Co-authored-by: Starefossen <968267+Starefossen@users.noreply.github.com>
Copilot AI and others added 2 commits February 16, 2026 11:55
Co-authored-by: Starefossen <968267+Starefossen@users.noreply.github.com>
Co-authored-by: Starefossen <968267+Starefossen@users.noreply.github.com>
Copilot AI changed the title [WIP] Add a prerequisites section for workshops Add prerequisites field for workshop proposals Feb 16, 2026
Copilot AI requested a review from Starefossen February 16, 2026 12:04
@Starefossen Starefossen marked this pull request as ready for review February 16, 2026 12:13
@Starefossen Starefossen requested a review from a team as a code owner February 16, 2026 12:13
@qodo-code-review
Copy link
Copy Markdown

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Validation Gap

prerequisites is accepted as an optional string but does not appear to enforce non-empty/trimmed content. As implemented, empty strings (or whitespace-only values) may be persisted and then treated as “present” in UI rendering, which can lead to confusing display behavior. Consider normalizing (trim) and/or transforming empty strings to undefined, similar to other optional text inputs.

  .min(1, 'At least one audience must be specified'),
outline: z.string().nullable().optional().transform(nullToUndefined),
topics: z.array(ReferenceSchema).min(1, 'At least one topic is required'),
tos: z.boolean().refine((val) => val === true, {
  message: 'Terms of Service must be accepted',
}),
video: z.string().nullable().optional().transform(nullToUndefined),
capacity: z.number().nullable().optional().transform(nullToUndefined),
prerequisites: z.string().nullable().optional().transform(nullToUndefined),
speakers: z
Data Normalization

Local state initializes prerequisites as an empty string and always pushes it to the parent proposal state. This can cause prerequisites: "" to be submitted even when the field is not shown (non-workshop formats), which may bypass intended “optional/absent” semantics and interact poorly with conditional visibility/display. Consider only including the field when workshop format, or normalizing empty string to undefined before calling setProposal.

const [prerequisites, setPrerequisites] = useState(
  proposal?.prerequisites ?? '',
)

// Push local state changes to parent
useEffect(() => {
  setProposal({
    title,
    language,
    description,
    format,
    level,
    audiences,
    topics,
    outline,
    tos,
    prerequisites,
  })
}, [
  title,
  language,
  description,
  format,
  level,
  audiences,
  topics,
  outline,
  tos,
  prerequisites,
  setProposal,
Conditional Visibility

The hidden logic checks both workshop format and whether prerequisites is non-null/defined, but the current condition may still show the field for empty strings and includes a redundant null check given the typing. Consider tightening the condition to treat empty/whitespace-only values as absent, and simplifying the null/undefined checks to match the actual stored type.

defineField({
  name: 'prerequisites',
  title: 'Prerequisites',
  type: 'text',
  description:
    'Prerequisites for workshop participants (e.g., "Bring a computer with Docker installed")',
  hidden: ({ document }) => {
    const format = document?.format as string | undefined
    const prerequisites = document?.prerequisites as string | undefined
    const isWorkshop =
      format === 'workshop_120' || format === 'workshop_240'
    return !(
      isWorkshop ||
      (prerequisites !== undefined && prerequisites !== null)
    )
  },
}),

@qodo-code-review
Copy link
Copy Markdown

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
General
Add backend validation for prerequisites

Add a .refine() check to ProposalInputSchema to validate that prerequisites are
only provided for workshop formats, enforcing this rule on the backend.

src/server/schemas/proposal.ts [40-60]

 export const ProposalInputSchema = ProposalBaseSchema.extend({
   description: z
     .array(z.any())
     .refine(
       (val) =>
         Array.isArray(val) &&
         val.length > 0 &&
         val.every(isPortableTextElement),
       {
         message: 'Description cannot be empty',
       },
     ),
   topics: z.array(ReferenceSchema).min(1, 'At least one topic is required'),
   tos: z.boolean().refine((val) => val === true, {
     message: 'Terms of Service must be accepted',
   }),
   video: z.string().nullable().optional().transform(nullToUndefined),
   capacity: z.number().nullable().optional().transform(nullToUndefined),
   prerequisites: z.string().nullable().optional().transform(nullToUndefined),
   speakers: z
     .array(ReferenceSchema)
     .nullable()
     .optional()
     .transform(nullToUndefined),
-})
+}).refine(
+  (data) => {
+    if (data.prerequisites && !isWorkshopFormat(data.format)) {
+      return false
+    }
+    return true
+  },
+  {
+    message: 'Prerequisites are only allowed for workshop formats.',
+    path: ['prerequisites'],
+  },
+)

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a missing backend validation and proposes adding a .refine() check to enforce that prerequisites are only submitted for workshop formats, which is crucial for data integrity.

Medium
Normalize empty prerequisites to undefined

In the Zod schema, trim the prerequisites string and transform empty or
whitespace-only values to undefined to ensure data consistency.

src/server/schemas/proposal.ts [54]

-prerequisites: z.string().nullable().optional().transform(nullToUndefined),
+prerequisites: z.string().trim().nullable().optional().transform((val) => {
+  const trimmed = val?.trim()
+  return trimmed ? trimmed : undefined
+}),
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: This suggestion improves data quality by ensuring that empty or whitespace-only strings for prerequisites are normalized to undefined, preventing inconsistent data from being stored.

Low
Possible issue
Clear stale prerequisites on format change

Add a useEffect hook that clears the prerequisites state if the proposal format
is changed to a non-workshop type.

src/components/proposal/ProposalDetailsForm.tsx [61-63]

 const [prerequisites, setPrerequisites] = useState(
   proposal?.prerequisites ?? '',
 )
+useEffect(() => {
+  if (!isWorkshopFormat(format)) {
+    setPrerequisites('')
+  }
+}, [format])
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a UI state bug where prerequisites are not cleared when switching to a non-workshop format, and it provides a concise useEffect hook to fix it, preventing incorrect data submission.

Medium
  • More

@Starefossen
Copy link
Copy Markdown
Member

@copilot review the code reivew comments from qodo in this pull request

… handling for prerequisites

Co-authored-by: Starefossen <968267+Starefossen@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 16, 2026

@copilot review the code reivew comments from qodo in this pull request

I've addressed all three Qodo code review suggestions in commit 67a6fe7:

1. Backend Validation - Added .refine() check to reject prerequisites on non-workshop formats
2. Data Normalization - Trim and transform empty/whitespace-only strings to undefined
3. Format Change Handling - Clear prerequisites when switching from workshop to non-workshop format

Also added 3 comprehensive tests covering:

  • Rejecting prerequisites for non-workshop formats
  • Normalizing empty/whitespace to undefined
  • Trimming whitespace from valid prerequisites

All quality checks pass: TypeScript ✓, ESLint ✓, Prettier ✓, Tests ✓ (1,536 total)

@Starefossen Starefossen merged commit 8e87183 into main Feb 16, 2026
9 checks passed
@Starefossen Starefossen deleted the copilot/add-prerequisites-section branch February 16, 2026 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a prerequisites section for workshops

2 participants