Skip to content

Repository files navigation

Trial Task — Membership Plan Carousel + Cart + Checkout Flow (Stripe)

Goal

Build a data-driven, reusable membership plan UI (based on the provided screenshots) that cycles through plans in a carousel, includes a global cart in the navbar, and implements a full checkout flow with a dedicated cart/checkout page using Stripe.

This task is focused on:

  • Component design and reusability
  • State management across pages
  • Clean UI implementation
  • Integrating a real payment provider (Stripe) using Next.js API routes
  • Basic cart and checkout architecture

Stripe keys will be provided separately.


Tech assumptions

  • Next.js + React + TypeScript.
  • Use Tailwind CSS for styling
  • State management is up to you:
    • You may use local state, React Context, Zustand, Redux, etc.
    • If unsure, React Context is recommended.
  • Stripe must be fully integrated using Next.js API routes.


Fonts & Colours

  • Import Work Sans from Google Fonts and use across the whole site
  • Colour codes are as follows:
    • Nav Background/Brand Color: #022a25
    • Membership Bar on Carousel:
      • Bronze: #f59e0b
      • Silver: #cbd5e1
      • Gold: #fde047

Icons

  • Import Icons from any icon library of your choice (react.feather or HeroIcons recommended)
  • Plans page must match the 'Part A - Plan Screen.pdf' file in to the 'public' folder of the project.
  • 9 different icons are required on the Plans Page. Match the sizes and colours shown in the PDF as closely as possible.

Provided data (single source of truth)

Use this array to render plan names and prices. This must be the only source of pricing data.

interface Product {
  id: number;
  name: string;
  monthlyPrice: number;
  totalMonthlyPrice: number;
  totalMonthlySavings: number;
  totalAnnualPrice: number;
}

export const products: Product[] = [
  {
    id: 1,
    name: 'Bronze Membership',
    monthlyPrice: 140,
    totalMonthlyPrice: 1680,
    totalMonthlySavings: 420,
    totalAnnualPrice: 2140,
  },
  {
    id: 2,
    name: 'Silver Membership',
    monthlyPrice: 240,
    totalMonthlyPrice: 2880,
    totalMonthlySavings: 3420,
    totalAnnualPrice: 540,
  },
  {
    id: 3,
    name: 'Gold Membership',
    monthlyPrice: 340,
    totalMonthlyPrice: 3680,
    totalMonthlySavings: 820,
    totalAnnualPrice: 6820,
  },
];

Part A — Membership Plans Carousel

Core requirement

Build a carousel that displays one plan at a time and allows switching between plans using left/right navigation arrows (like the Plan Screen screenshot).

The carousel must be:

  • Data-driven
  • Reusable
  • Generated by mapping over the products array
  • Not hardcoded to exactly 3 slides

Reusable component API

Create a reusable component similar to: MembershipPlansCarousel({ products })

Where:

  • products is an array of Product
  • The component maps over products to generate slides
  • The component should work for any length of products

Recommended internal structure

  • MembershipPlansCarousel → handles carousel logic + navigation
  • PlanSlide → renders UI for a single plan

Data → UI mapping (must follow exactly)

These values must come from the Product fields (not hardcoded) and must be formatted as currency.

UI Element Data field
Top header title product.name
Main price on the right product.monthlyPrice
Monthly option “Annual Cost” product.totalMonthlyPrice
Annual option “Annual Cost” product.totalAnnualPrice
“Your Savings” product.totalMonthlySavings

Example for Silver

  • $240.00*monthlyPrice
  • $2,880.00totalMonthlyPrice
  • $3,420.00totalAnnualPrice
  • $540.00totalMonthlySavings

UI structure per slide

Each slide should visually follow the Plan Screen screenshot.

Left column — Membership Information

  • Header: “Membership Information”
  • Row of 3 icons + labels (static content is fine)
  • Feature list with green check / red cross icons (static content is fine)

This feature list does not need to come from data and can be hardcoded once.


Right column — Payment Information

  • Header: “Payment Information”
  • Large price text showing product.monthlyPrice
  • Two static contact buttons:
    • “Speak To Our Team”
    • “Chat With Our Team”
  • “Select a payment option below” section:
    • Monthly Fee and Annual Fee selectable options
    • “Annual Cost” row showing both totals
    • “Your Savings” row
    • “12-Month Contract” row (static icons are fine)
  • “Purchase Membership” button
    • When clicked, user is taken to /checkout

Payment option selection behavior

  • Implement UI state for Monthly vs Annual
  • Selected option must be visually highlighted
  • This selection must be persisted and available on the cart/checkout page

Currency formatting

All money values must:

  • Include dollar sign
  • Include comma separators
  • Always show 2 decimals

Examples

  • 240$240.00
  • 2880$2,880.00

Cart button in Navigation

Requirement

A global navigation bar has been created for you in the template file. Add the functionality to this button to update with the Monthly Price for the product the user selects when they click the "Purchase Memebership" button at the bottom of the page.

Follow the Cart Behaviour instructions below


Cart behavior

The cart represents the currently selected membership plan.

When a user selects a membership and clicks “Purchase Membership”:

  • The selected plan must be added to the cart
  • The cart must display:
    • Selected plan name
    • Selected billing type (Monthly / Annual)
    • Final price

The cart does not need to support multiple items — it can be treated as a single-item cart.


State management

Cart state must persist across pages.

You may use:

  • React Context (recommended if unsure)
  • Zustand / Redux / Jotai
  • Or URL params (if cleanly implemented)

The same state should be used for:

  • Carousel selection
  • Cart display
  • Checkout page

UI requirements

  • Cart should be visible in the navbar at all times
  • Cart should clearly show the current Monthly Price
  • If no membership is selected:
    • Cart should show an empty state (e.g. “No plan selected”)

Navigation behavior

  • Clicking the cart (or checkout button in navbar) should navigate to /checkout
  • The checkout page must reflect the same data shown in the cart

Acceptance Checklist — Navbar Cart Button

  • Cart displays selected membership
  • Cart displays correct price
  • Cart persists across page navigation
  • Clicking cart navigates to /checkout
  • Cart state matches checkout state

Part B — Cart Page (/cart)

This page represents a pre-checkout cart summary where the user reviews their membership before proceeding to the full checkout.


Requirement

This page acts as a cart review step only (no payment processing here).

The selected membership and billing option must be available on this page via state management.


Cart page structure

Section 1 — Membership Summary

Ensure the Cart page displays the following product values from the user's selected product via state (values required will be indicated in the comments on the page which you will be required to map correctly and display via state):

  • Selected plan name
  • Selected billing type (Monthly / Annual)
  • Base price (ex GST)
  • GST amount (assume 10%)
  • Final total to pay today

This data must come from the same state as the carousel selection.


Section 2 — Terms & Conditions

  • Checkbox:
    “I have read and agree to the Terms & Conditions of this membership.”
  • The Proceed to Checkout button must be disabled until this is checked.

Section 3 — Proceed to Checkout

  • Button: “Proceed to Checkout”
  • Navigates to /checkout

Acceptance Checklist — Cart Page

  • Displays selected membership
  • Shows correct pricing + GST
  • Terms checkbox required to continue
  • Button navigates to /checkout
  • No Stripe logic on this page

Part C — Checkout Page (/checkout)

This is the final payment step.


Requirement

Create a route at /checkout that contains:

  • Customer details form
  • Membership summary
  • Stripe payment form

This page performs the actual Stripe payment.


Checkout page structure

Section 1 — Customer Details Form (Left side)

All required form fields have been created for you.

All fields must be controlled inputs.

Basic validation required:

  • Required fields must be filled
  • Email must be valid format

Section 2 — Membership Summary (Right side)

Ensure the Checkout page displays the following product values from the user's selected product via state (Values required will be indicated in the comments on the page which you will be required to map correctly and display via state):

  • Selected plan name
  • Selected billing type (Monthly / Annual)
  • Base price (ex GST)
  • GST amount (10%)
  • Final total to pay today

Must use the same state as the cart page.


Section 3 — Payment Details (Stripe)

Integrate Stripe Elements to collect card details:

  • Card number
  • Expiry
  • CVC

Do not build custom card inputs.

Use official Stripe Elements components.


Stripe Integration (Required)

This must be a real Stripe integration using:

  • Stripe SDK
  • Stripe Elements (frontend)
  • Next.js API routes (backend)

Stripe keys will be provided separately.


Stripe Test Keys & Testing

You will be provided with Stripe test API keys separately.

These keys should be used for all development and testing.
Do not use real/live Stripe keys.


Test card details

When testing payments with Stripe, you may use the following test card:

Card number: 4242 4242 4242 4242
Expiry: Any future date (e.g. 12/34)
CVC: Any 3 digits (e.g. 123)
ZIP / Postal code: Any valid value

This card should always result in a successful test payment.


Notes

  • All payments must be made in Stripe test mode
  • No real money will be charged
  • The success state should be handled exactly the same way as a real payment
  • Do not commit Stripe keys to the repository (use environment variables)

Backend (Next.js API route)

Create an API route such as:

POST /api/create-payment-intent

This route should:

Receive:

  • Selected product
  • Billing type
  • Final price (including GST)

Then:

  • Create a Stripe PaymentIntent
  • Return client_secret to the frontend

Frontend payment flow

On checkout form submit:

  1. Validate customer details
  2. Call /api/create-payment-intent
  3. Use Stripe Elements to confirm card payment
  4. On success:
    • Show success message or screen
    • Clear cart and checkout state

No webhooks required for this task.


State Management Requirement

You must persist across pages:

  • Selected product
  • Monthly vs Annual choice
  • Cart data

State management is up to you:

  • React Context (recommended if unsure)
  • Zustand / Redux / Jotai
  • Or URL params (if cleanly implemented)

Acceptance Checklist — Checkout

  • Customer form exists and validates
  • Membership summary matches cart
  • Stripe Elements used for card input
  • Next.js API creates PaymentIntent
  • Real Stripe payment works end-to-end
  • Success state shown after payment
  • Cart state cleared after success

Acceptance Checklist

Carousel

  • Slides generated by mapping over products
  • Title uses product.name
  • Main price uses product.monthlyPrice
  • Monthly “Annual Cost” uses product.totalMonthlyPrice
  • Annual “Annual Cost” uses product.totalAnnualPrice
  • “Your Savings” uses product.totalMonthlySavings
  • Monthly/Annual toggle is interactive
  • Currency formatting is correct
  • Clicking “Purchase Membership” navigates to /cart

Cart Page (/cart)

  • Selected plan persists from plans page
  • Displays selected plan name and billing type
  • Base price (ex GST) displayed correctly
  • GST (10%) calculated correctly
  • Final total to pay today is correct
  • Proceed button disabled until Terms are accepted
  • Clicking “Proceed to Checkout” navigates to /checkout

Checkout Page (/checkout)

  • Customer details form exists and is controlled
  • Required fields are validated
  • Membership summary matches cart
  • GST and totals calculated correctly
  • Stripe Elements used for card input
  • Next.js API route creates PaymentIntent
  • Real Stripe payment works end-to-end
  • Success state shown after payment
  • Cart / checkout state cleared after success

Global State & Navigation

  • Global navbar exists on all pages
  • Cart visible in navbar
  • Cart displays correct selected price
  • Cart state persists across page navigation
  • Cart state, checkout state, and carousel state all stay in sync

Submission

To complete this task, you must deploy a working version of the application and provide a live link.


Requirements

  1. Push the full project to your own GitHub repository
  2. Create a new project on your own Vercel account
  3. Deploy the project to Vercel
  4. Ensure the application works in the production environment

Testing requirements

You must successfully test all three membership products in production:

  • Bronze Membership
  • Silver Membership
  • Gold Membership

For each product:

  • Select the membership on the plans page
  • Proceed through cart and checkout
  • Complete a Stripe payment using test keys
  • Reach the success state
  • Redirect the user to the /plans page after payment is completed

All three products must complete the full flow successfully.


Submission

Submit the following:

  • Public GitHub repository link
  • Live Vercel deployment URL

The Vercel link should allow:

  • Browsing plans
  • Adding to cart
  • Completing checkout
  • Making Stripe test payments end-to-end

No local or development-only links will be accepted.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages