From c35911f4697db0a02235d59ef99422f58607e049 Mon Sep 17 00:00:00 2001 From: FinleyNeilson Date: Sun, 26 Apr 2026 15:57:39 +1200 Subject: [PATCH 01/17] feat: add placeholder form routing --- src/app/form/page.tsx | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/app/form/page.tsx diff --git a/src/app/form/page.tsx b/src/app/form/page.tsx new file mode 100644 index 0000000..0d9d943 --- /dev/null +++ b/src/app/form/page.tsx @@ -0,0 +1,11 @@ +export default function Blog() { + return ( +
+
+

Form

+ +

Placeholder Form

+
+
+ ); +} From 588683bf8605affb5638805f1cf832b9c0337f7d Mon Sep 17 00:00:00 2001 From: FinleyNeilson Date: Sun, 26 Apr 2026 16:31:50 +1200 Subject: [PATCH 02/17] feat: update basic form with info from LUG form --- src/app/form/page.tsx | 71 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/src/app/form/page.tsx b/src/app/form/page.tsx index 0d9d943..6e0b323 100644 --- a/src/app/form/page.tsx +++ b/src/app/form/page.tsx @@ -1,11 +1,68 @@ -export default function Blog() { +export default function FormPage() { return ( -
-
-

Form

+
+

LUG@UoA Member Registration Form 2026

+

{`Thank you for registering your interest to become a member of the + University of Auckland Linux User Group (also known as LUG@UoA)! It's + great to have you with us. The details collected in this form will be + used for record-keeping purposes as mandated by Student Groups and to + send you relevant communication about the user group, as well as to + identify areas of interest for the club. We will not otherwise use or + transfer your information. You can modify or withdraw your response by + contacting lug.aucklanduni@gmail.com.`}

-

Placeholder Form

-
-
+
+
+ + +
+ +
+ + Have you registered with us previously and meet the following + conditions? + + +
    +
  • You are a current student at the University of Auckland
  • +
  • + You previously gave us your UPI or Student ID when registering + your interest in 2025 +
  • +
  • + You have not changed your programme of study since your last + application +
  • +
+ +

+ + { + "If you are signing up for the first time, you should select 'no'" + } + +

+ +
+ + + +
+
+ + +
+ ); } From 7ecf7bd152b374343c8f808115be49bc651d2d9d Mon Sep 17 00:00:00 2001 From: FinleyNeilson Date: Sun, 26 Apr 2026 16:40:30 +1200 Subject: [PATCH 03/17] feat: add basic server action for createRegistrationForm --- src/app/form/actions.ts | 12 ++++++++++++ src/app/form/page.tsx | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/app/form/actions.ts diff --git a/src/app/form/actions.ts b/src/app/form/actions.ts new file mode 100644 index 0000000..595cc0d --- /dev/null +++ b/src/app/form/actions.ts @@ -0,0 +1,12 @@ +"use server"; + +import { redirect } from "next/navigation"; + +export async function createRegistrationForm(formData: FormData) { + const email = formData.get("email"); + const previouslyRegistered = formData.get("previouslyRegistered"); + + console.log("New Registration Attempt:", { email, previouslyRegistered }); + + redirect("/form/success"); +} diff --git a/src/app/form/page.tsx b/src/app/form/page.tsx index 6e0b323..b7c934b 100644 --- a/src/app/form/page.tsx +++ b/src/app/form/page.tsx @@ -1,3 +1,5 @@ +import { createRegistrationForm } from "./actions"; + export default function FormPage() { return (
@@ -11,7 +13,7 @@ export default function FormPage() { transfer your information. You can modify or withdraw your response by contacting lug.aucklanduni@gmail.com.`}

-
+
From b494a9dc06947a527bcf99d4abb83c932d50bc69 Mon Sep 17 00:00:00 2001 From: Sonja Date: Mon, 27 Apr 2026 16:12:08 +1200 Subject: [PATCH 04/17] feat(form): add form pages, basic branching logic (#32) add form pages with information from original member registration form add branching logic for each page depending on user selections --- src/app/form/actions.ts | 31 ++++- src/app/form/page.tsx | 70 ++++------- src/app/form/pages/FinalPage.tsx | 102 ++++++++++++++++ src/app/form/pages/NewMemberPage.tsx | 47 ++++++++ src/app/form/pages/NewOtherPage.tsx | 49 ++++++++ src/app/form/pages/NewUoaPage.tsx | 153 ++++++++++++++++++++++++ src/app/form/pages/ReturningUoaPage.tsx | 39 ++++++ src/app/form/pages/StartPage.tsx | 60 ++++++++++ 8 files changed, 501 insertions(+), 50 deletions(-) create mode 100644 src/app/form/pages/FinalPage.tsx create mode 100644 src/app/form/pages/NewMemberPage.tsx create mode 100644 src/app/form/pages/NewOtherPage.tsx create mode 100644 src/app/form/pages/NewUoaPage.tsx create mode 100644 src/app/form/pages/ReturningUoaPage.tsx create mode 100644 src/app/form/pages/StartPage.tsx diff --git a/src/app/form/actions.ts b/src/app/form/actions.ts index 595cc0d..00885ae 100644 --- a/src/app/form/actions.ts +++ b/src/app/form/actions.ts @@ -3,10 +3,39 @@ import { redirect } from "next/navigation"; export async function createRegistrationForm(formData: FormData) { + const page = formData.get("page") as string; + const email = formData.get("email"); const previouslyRegistered = formData.get("previouslyRegistered"); + let nextPage; + switch (page) { + case "start": + const returning = formData.get("previouslyRegistered") as string; + nextPage = returning === "yes" ? "returningUoa" : "newMember"; + break; + case "returningUoa": + nextPage = "final"; + break; + case "newMember": + const attendsUoa = formData.get("attendUoa") as string; + nextPage = attendsUoa === "yes" ? "newUoa" : "newOther"; + break; + case "newUoa": + nextPage = "final"; + break; + case "newOther": + nextPage = "final"; + break; + case "final": + // redirect to success page + break; + default: + break; + } + console.log("New Registration Attempt:", { email, previouslyRegistered }); - redirect("/form/success"); + // redirect("/form/success"); + redirect(`/form?page=${nextPage}`); } diff --git a/src/app/form/page.tsx b/src/app/form/page.tsx index b7c934b..e59ce67 100644 --- a/src/app/form/page.tsx +++ b/src/app/form/page.tsx @@ -1,6 +1,18 @@ import { createRegistrationForm } from "./actions"; +import { StartPage } from "./pages/StartPage"; +import { ReturningUoaPage } from "./pages/ReturningUoaPage"; +import { NewMemberPage } from "./pages/NewMemberPage"; +import { NewUoaPage } from "./pages/NewUoaPage"; +import { NewOtherPage } from "./pages/NewOtherPage"; +import { FinalPage } from "./pages/FinalPage"; + +export default async function FormPage({ + searchParams, +}: { + searchParams: Promise<{ page?: string }>; +}) { + const { page = "start" } = await searchParams; -export default function FormPage() { return (

LUG@UoA Member Registration Form 2026

@@ -14,54 +26,14 @@ export default function FormPage() { contacting lug.aucklanduni@gmail.com.`}

-
- - -
- -
- - Have you registered with us previously and meet the following - conditions? - - -
    -
  • You are a current student at the University of Auckland
  • -
  • - You previously gave us your UPI or Student ID when registering - your interest in 2025 -
  • -
  • - You have not changed your programme of study since your last - application -
  • -
- -

- - { - "If you are signing up for the first time, you should select 'no'" - } - -

- -
- - - -
-
+ + + {page === "start" && } + {page === "returningUoa" && } + {page === "newMember" && } + {page === "newUoa" && } + {page === "newOther" && } + {page === "final" && } diff --git a/src/app/form/pages/FinalPage.tsx b/src/app/form/pages/FinalPage.tsx new file mode 100644 index 0000000..8cd3bf1 --- /dev/null +++ b/src/app/form/pages/FinalPage.tsx @@ -0,0 +1,102 @@ +export function FinalPage() { + return ( + <> +

The Final Section

+

+ { + "Some final questions from us about who you are, and what you're looking forward to!" + } +

+ + + +

final section placeholder

+ +
+

{"How much do you currently know about Linux?*"}

+

+ { + "Everyone is welcome, regardless of skill level or operating system choice!" + } +

+
+ + + + + + + + + + + +
+
+ +
+

{"What is your potential involvement in the LUG?"}

+

+ Checking any of these boxes will add you to our email newsletter. You + can unsubscribe at any time by emailing lug.aucklanduni@gmail.com +

+ +
+ + + + + + + +
+
+ +
+

What is your Discord username or handle?

+

+ LUG@UoA hosts a Discord server where members can discuss Linux, free + and open source software and technology in general. The Discord link + will be shown when you submit this form. +

+
+ + ); +} diff --git a/src/app/form/pages/NewMemberPage.tsx b/src/app/form/pages/NewMemberPage.tsx new file mode 100644 index 0000000..46b73cb --- /dev/null +++ b/src/app/form/pages/NewMemberPage.tsx @@ -0,0 +1,47 @@ +export function NewMemberPage() { + return ( + <> +

Name & University Status

+ + + +
+

What is your first name?*

+
+ +
+

And your last name?*

+

If you do not have a last name, type N/A.

+
+ +
+

{"Do you attend The University of Auckland (UoA)?*"}

+ + + +
+ + ); +} diff --git a/src/app/form/pages/NewOtherPage.tsx b/src/app/form/pages/NewOtherPage.tsx new file mode 100644 index 0000000..33a3e93 --- /dev/null +++ b/src/app/form/pages/NewOtherPage.tsx @@ -0,0 +1,49 @@ +export function NewOtherPage() { + return ( + <> +

Your affiliation

+ + + +
+

+ What institution or organisation are you affiliated with the most?* +

+

+ This can be the name of your university, your company, your research + lab, etc. +

+
+ +
+

Tell us more about yourself

+

+ A nice excerpt about yourself can allow us to identify you in future + club events. +

+
+ +
+

Why do you want to join our club?

+

Here is your chance to pitch yourself to us!

+
+ + ); +} diff --git a/src/app/form/pages/NewUoaPage.tsx b/src/app/form/pages/NewUoaPage.tsx new file mode 100644 index 0000000..2adcf49 --- /dev/null +++ b/src/app/form/pages/NewUoaPage.tsx @@ -0,0 +1,153 @@ +export function NewUoaPage() { + return ( + <> +

Your student details with The University of Auckland

+

+ { + "As a registered club at the University of Auckland, we are required to collect information about our members who are UoA students or staff." + } +

+ + + +
+

What is your username/UPI?*

+

i.e. jbon007

+
+ +
+

And your student ID?*

+

i.e. 825179213

+
+ +
+

{"What faculty or faculties are you enrolled in?*"}

+

If we miss your faculty, let us know!

+ +
+ + + + + + + + + + + + + + + + + + +
+
+ +
+

What is your current programme of study?*

+

+ e.g. Bachelor of Engineering (Honours), Bachelor of Science, Master of + Arts, etc. +

+
+ +
+

{"What is your current year of study?"}

+

+ { + "Note to those who have progressed from one degree to another at UoA (e.g. from undergrad to postgrad, from one Bachelor degree to another): Your year of study is based on your current degree, not the total number of years that you have accumulated at UoA. For instance, if it is your first year doing a Master's degree after doing a Bachelor's degree, then you are at your 1st Year." + } +

+
+ + + + + + + + + + + +
+
+ + ); +} diff --git a/src/app/form/pages/ReturningUoaPage.tsx b/src/app/form/pages/ReturningUoaPage.tsx new file mode 100644 index 0000000..baf3cb2 --- /dev/null +++ b/src/app/form/pages/ReturningUoaPage.tsx @@ -0,0 +1,39 @@ +export function ReturningUoaPage() { + return ( + <> +

Returning UoA Students

+

+ We have two questions from you in this section, and then a few more + questions to wrap things up. +

+ + + +
+

What is your username/UPI?*

+

i.e. jbon007

+
+ +
+

And your student ID?*

+

i.e. 825179213

+
+ + ); +} diff --git a/src/app/form/pages/StartPage.tsx b/src/app/form/pages/StartPage.tsx new file mode 100644 index 0000000..fa6ee50 --- /dev/null +++ b/src/app/form/pages/StartPage.tsx @@ -0,0 +1,60 @@ +export function StartPage() { + return ( + <> + + +
+ + +
+ +
+ + Have you registered with us previously and meet the following + conditions?* + + +
    +
  • You are a current student at the University of Auckland
  • +
  • + You previously gave us your UPI or Student ID when registering your + interest in 2025 +
  • +
  • + You have not changed your programme of study since your last + application +
  • +
+ +

+ + {"If you are signing up for the first time, you should select 'no'"} + +

+ +
+ + + +
+
+ + ); +} From 205742bdd64b895f409ed8aecdca1d57ccc1c79f Mon Sep 17 00:00:00 2001 From: sonjali4 Date: Wed, 29 Apr 2026 19:25:50 +1200 Subject: [PATCH 05/17] feat/add pattern checking validation --- src/app/form/pages/NewUoaPage.tsx | 2 ++ src/app/form/pages/ReturningUoaPage.tsx | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/app/form/pages/NewUoaPage.tsx b/src/app/form/pages/NewUoaPage.tsx index 2adcf49..e974615 100644 --- a/src/app/form/pages/NewUoaPage.tsx +++ b/src/app/form/pages/NewUoaPage.tsx @@ -19,6 +19,7 @@ export function NewUoaPage() { id="upi" type="text" placeholder="Your answer" + pattern="[a-z]{3,4}[0-9]{3}" required />
@@ -32,6 +33,7 @@ export function NewUoaPage() { id="studentId" type="text" placeholder="Your answer" + pattern="[0-9]{9,10}" required /> diff --git a/src/app/form/pages/ReturningUoaPage.tsx b/src/app/form/pages/ReturningUoaPage.tsx index baf3cb2..f9d601b 100644 --- a/src/app/form/pages/ReturningUoaPage.tsx +++ b/src/app/form/pages/ReturningUoaPage.tsx @@ -16,8 +16,9 @@ export function ReturningUoaPage() { @@ -29,8 +30,9 @@ export function ReturningUoaPage() { From c6b742f005925f20e871e5c6ae1976ea7a0d1c95 Mon Sep 17 00:00:00 2001 From: FinleyNeilson Date: Thu, 30 Apr 2026 14:39:54 +1200 Subject: [PATCH 06/17] feat: Add more specific error messages also start refactor for client side checking --- src/app/form/actions.ts | 66 ++++++++++++++++++++++++-------- src/app/form/page.tsx | 9 ++--- src/app/form/pages/StartPage.tsx | 18 ++++++++- 3 files changed, 70 insertions(+), 23 deletions(-) diff --git a/src/app/form/actions.ts b/src/app/form/actions.ts index 00885ae..47801c7 100644 --- a/src/app/form/actions.ts +++ b/src/app/form/actions.ts @@ -2,40 +2,76 @@ import { redirect } from "next/navigation"; -export async function createRegistrationForm(formData: FormData) { +// 1. Update the type to include 'fields' +export type FormState = { + error?: string; + fields?: { + email?: string; + previouslyRegistered?: string; + }; +} | null; + +export async function createRegistrationForm( + prevState: FormState, + formData: FormData, +) { const page = formData.get("page") as string; - const email = formData.get("email"); - const previouslyRegistered = formData.get("previouslyRegistered"); + const email = formData.get("email") as string; + const previouslyRegistered = formData.get("previouslyRegistered") as string; + + let nextPage: string = "start"; - let nextPage; switch (page) { case "start": - const returning = formData.get("previouslyRegistered") as string; - nextPage = returning === "yes" ? "returningUoa" : "newMember"; - break; - case "returningUoa": - nextPage = "final"; + // Check Email + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + + if (!email || !emailRegex.test(email)) { + return { + error: "Please enter a valid email address (e.g., name@example.com).", + fields: { email, previouslyRegistered }, + }; + } + + if (!previouslyRegistered) { + return { + error: "Please select whether you have registered previously.", + fields: { email }, // Keep the email so they don't have to re-type it + }; + } + + nextPage = previouslyRegistered === "yes" ? "returningUoa" : "newMember"; break; + case "newMember": const attendsUoa = formData.get("attendUoa") as string; + if (!attendsUoa) { + return { + error: "Please select an option.", + fields: { email, previouslyRegistered }, + }; + } nextPage = attendsUoa === "yes" ? "newUoa" : "newOther"; break; + + case "returningUoa": case "newUoa": - nextPage = "final"; - break; case "newOther": nextPage = "final"; break; + case "final": - // redirect to success page + // Final submission logic + console.log("Finalizing registration for:", email); + redirect("/success"); break; + default: + nextPage = "start"; break; } - console.log("New Registration Attempt:", { email, previouslyRegistered }); - - // redirect("/form/success"); + // Redirect to the next step redirect(`/form?page=${nextPage}`); } diff --git a/src/app/form/page.tsx b/src/app/form/page.tsx index e59ce67..0cde036 100644 --- a/src/app/form/page.tsx +++ b/src/app/form/page.tsx @@ -5,6 +5,7 @@ import { NewMemberPage } from "./pages/NewMemberPage"; import { NewUoaPage } from "./pages/NewUoaPage"; import { NewOtherPage } from "./pages/NewOtherPage"; import { FinalPage } from "./pages/FinalPage"; +import { RegistrationForm } from "./RegistrationForm"; export default async function FormPage({ searchParams, @@ -25,18 +26,14 @@ export default async function FormPage({ transfer your information. You can modify or withdraw your response by contacting lug.aucklanduni@gmail.com.`}

-
- - + {page === "start" && } {page === "returningUoa" && } {page === "newMember" && } {page === "newUoa" && } {page === "newOther" && } {page === "final" && } - - - +
); } diff --git a/src/app/form/pages/StartPage.tsx b/src/app/form/pages/StartPage.tsx index fa6ee50..96c7864 100644 --- a/src/app/form/pages/StartPage.tsx +++ b/src/app/form/pages/StartPage.tsx @@ -1,4 +1,10 @@ +"use client"; + +import { useFormError } from "../RegistrationForm"; + export function StartPage() { + const state = useFormError(); + return ( <> @@ -9,9 +15,12 @@ export function StartPage() { name="email" id="email" type="email" - placeholder="Your email" - required + defaultValue={state?.fields?.email || ""} // This is what prevents the clearing + className={`border p-2 w-full ${state?.error?.includes("email") ? "border-red-500" : "border-gray-300"}`} /> + {state?.error?.includes("email") && ( +

{state.error}

+ )}
@@ -38,6 +47,11 @@ export function StartPage() {

+ {/* Only show the error here if it's about the registration status */} + {state?.error?.includes("registered") && ( +

{state.error}

+ )} +