Overview
Qasa is an event-ticketing product with an attendee side (discover events, buy tickets, share and transfer them) and an organiser side (create events, sell tickets, see sales, manage promotions). I worked on its React + TypeScript web app for eight months, one of its two main contributors, delivering sprint tickets end to end.
Attendee features and fixes
- Purchase to receipt. After buying, users were not always redirected to their receipt, and free tickets had their own redirect bug. Both now land on the receipt page.
- Sharing and transfers. Sharing several tickets at once was broken. Transfers now show a clear toast built from the API's response, whether it succeeded or failed.
- Pricing. Events show a dynamic "from" price on the homepage and ticket pages, driven by a new
starting_pricefield. - Wallet. Fixed a wallet that could display a negative balance.
- Discovery. Sensible empty states when no events match a search, event images handled dynamically across pages, and the Qasa microsite merged into the events site.
Organiser features
- Waitlists. Attendees can join an event's waitlist, and organisers can send a mass message to everyone on it. The success message comes from the backend response, not a hard-coded string.
- Promo codes. A full listing of promo codes, fixes to creation and visibility, and toggling codes active or inactive with feedback on the new state.
- Sales. The event sales view showed the last purchaser's name on every ticket, which is now fixed, and sales data is ordered newest first. The event summary report UI was also updated.
- Event creation. Currency became a required field, ticket-field defaults were fixed, and a location-address dropdown bug was resolved.
Later: funding applications
On the Qasa funding site (PHP), I built the submission flow for event and project funding applications. I also moved its emails onto the Mango Fund API and updated the trader onboarding guides.
What it taught me
Most of this work was careful, unglamorous sprint delivery in a shared codebase: reading the ticket, reproducing the bug, fixing the edge case, and checking the fix against what the backend actually returns. It's the habit behind everything I've built since.
