Engineering case study
Expo Management Solution
Building the frontend for expo operations
I designed and built the frontend for Expo Management Solution, from wireframes and workflows to REST API integration.
- My role
- Frontend Engineer
- Completed
- 2025
- Source code
- Private
At a glance
- Problem
- Give organizers and visitors clear steps for live prize draws and hall-specific voting.
- My ownership
- Frontend design, development, and REST API integration; eligibility enforcement remained in the backend.
- Key decision
- Separate draw setup from candidate review, and preserve voting answers for retries.
- Outcome & evidence
- Observed successful lottery and voting sessions at an event. No formal impact metrics were collected.
These screens illustrate the current implementation and the event workflow in a new visual design. Forma Design Expo, its visitors, dates and prizes are fictional; Washington, D.C. is an illustrative location. QR placeholders cannot be used for entry. The delivery account below describes my 2025 work.
Platform at a glance
- Visitor registration
- QR identity
- Event participation
Administration
Expos, roles, halls, stalls & exhibitors
Event operations
Entry, seminars, gifts & gala access
Engagement
Hall-specific voting & lottery draws
Reporting
Attendance, voting results & winners
The project
Expo Management Solution helps organizers manage an exhibition from registration through event-day activities and reporting. Visitors register through an expo landing page and receive a downloadable or printable QR identity. At the entrance, assigned staff scan that identity using a physical scanner connected to a computer with a public-facing display. Participating companies have their own dashboard for staff and invited VIP guests.
Discover the expo

My responsibility
I worked on event operations, authentication, permission-dependent screens, and engagement interfaces. Backend services handled eligibility checks and enforcement.
Event workspace

Frontend stack: JavaScript, Next.js 13, React 18, Tailwind CSS, DaisyUI, Axios, and React Hook Form.
Lottery and voting were two of the most challenging parts of my work. Both involved several steps, eligibility checks, and decisions about how the interface should respond.
Lottery: from eligible attendees to confirmed winners
Authorized staff configure lottery dates and prizes in their dashboard, then launch a dedicated full-screen draw for the audience. An announcer operates the draw while the accepted winners remain visible. Organizers use the lottery to draw prizes for visitors who attended within a selected date range. Each draw presents a candidate for review before the organizer confirms a winner.
Lottery workflow
From preparation to confirmed winners
01 / Configure
Prepare the draw in a separate setup modal.
- Lottery name
- Attendance range
- Set start and end dates
- Ranked prizes
- Assign existing prizes to positions
- Live Lottery Panel
02 / Run the draw
Select a prize position, then use Spin to request a candidate.
Prize selection
Choose a ranked position
Draw for its assigned prize.
Spin → Present candidateCandidate — awaiting review
03 / Review and confirm
Accept → Confirm winner
Reject → Spin again
Reject an absent or disqualified candidate. The backend excludes them from the entire lottery.
Closing the lottery requires confirmation. Once closed, Spin is disabled.
Lottery setup

I separated lottery setup from the live draw because they serve different tasks. Organizers could prepare dates and prize assignments together in a modal, then use a focused Lottery Panel during the event without configuration fields getting in the way.
Presenting a candidate was a separate step from accepting a winner. An organizer needed a chance to check whether the person was present and qualified before confirming them. The interface supported that decision; the backend handled eligibility and excluded rejected candidates from the entire lottery.
I also added confirmation before closing a lottery and disabled Spin once it was closed. If a draw request failed, the panel displayed the backend’s error message.
Voting: hall-specific questions and visitor choices
Each hall has a dedicated full-screen touchscreen voting booth, configured once during setup. Visitors operate it themselves, choosing stalls in response to questions for that hall; staff navigation and hall selection stay outside the ballot. Their QR identity is checked before they begin, and backend validation prevents repeat voting for the same hall.
Scan QR identity
Begin voting for the selected hall.
Check eligibility
Continue if eligible to vote.
Answer hall questions
Choose a stall for each question.
Submit vote
Finish after the last question.
Confirmation
See the thank-you screen.
Choose a stall

I kept the interface focused on one question at a time. Visitors could change their selection before advancing with Next, and Submit appeared on the final question. Each question started with a fresh selection; there was no Back action.
The tricky part was including the final answer in the submission. Updating React state and immediately submitting its existing value could leave that answer out. I built the updated answer array once, stored it in state, and passed the same array directly to the submission function.
While a request was pending, Submit was disabled to prevent repeated clicks. If it failed, the interface showed the error and kept the answers available for retry. Those answers stayed in memory only, so a page refresh cleared them. After a successful submission, a thank-you screen appeared and the flow reset after three seconds for the next visitor.
At the event
I watched organizers use the Lottery Panel at an event. The draw ran smoothly during the session I observed, and organizers and attendees appeared engaged throughout.
I also watched visitors answer a hall’s questions and submit their votes without problems.
These observations come from the sessions I attended; I didn’t collect performance or engagement metrics.