Skip to content

Commit a80f8ae

Browse files
committed
feat: Add payment instructions and support attendees feature in sponsorship flow
Signed-off-by: Steve Yonkeu <yokwejuste@yahoo.com>
1 parent 770329d commit a80f8ae

6 files changed

Lines changed: 38 additions & 7 deletions

File tree

src/data/ticketSponsor.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,11 @@ export const ticketSponsorEndpoint =
44
export const ticketSponsorSheetName = 'Ticket Sponsors';
55

66
export const paymentMethods = ['MTN Mobile Money (MoMo)', 'Orange Money (OM)'];
7+
8+
export const payTo = {
9+
mtn: '677123206',
10+
orange: '656246181',
11+
name: 'STEVE YONKEU',
12+
};
13+
14+
export const ticketPriceXAF = 3000;

src/i18n/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"viewAgenda": "View Agenda",
3838
"callForSpeakers": "Call For Speakers",
3939
"getYourTicket": "Get Your Ticket",
40+
"supportAttendees": "Support Attendees",
4041
"welcomeTitle": "Welcome to",
4142
"welcomeTitleHighlight": "PyCon Cameroon 2026",
4243
"welcomeText": "Join us for Cameroon's first-ever PyCon, a celebration of Python, technology, and African innovation. Experience two days of inspiring talks, hands-on workshops, and unforgettable networking opportunities in the vibrant city of Yaound\u00e9.",

src/i18n/fr.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"viewAgenda": "Voir l'agenda",
3838
"callForSpeakers": "Appel aux intervenants",
3939
"getYourTicket": "Obtenez votre billet",
40+
"supportAttendees": "Parrainer des participants",
4041
"welcomeTitle": "Bienvenue \u00e0",
4142
"welcomeTitleHighlight": "PyCon Cameroun 2026",
4243
"welcomeText": "Rejoignez-nous pour le tout premier PyCon du Cameroun, une c\u00e9l\u00e9bration de Python, de la technologie et de l'innovation africaine. Vivez deux jours de conf\u00e9rences inspirantes, d'ateliers pratiques et d'opportunit\u00e9s de r\u00e9seautage inoubliables dans la ville dynamique de Yaound\u00e9.",

src/index.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2398,6 +2398,17 @@ img {
23982398
flex-wrap: wrap;
23992399
}
24002400

2401+
@media (min-width: 992px) {
2402+
.hero-buttons {
2403+
flex-wrap: nowrap;
2404+
}
2405+
2406+
.hero-buttons .btn {
2407+
white-space: nowrap;
2408+
flex-shrink: 0;
2409+
}
2410+
}
2411+
24012412
.features {
24022413
background: linear-gradient(180deg, var(--color-dark) 0%, var(--color-black) 100%);
24032414
}

src/pages/Home.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import { Link } from 'react-router-dom';
33
import { useLocalizedPath } from '../hooks/useLocalizedPath';
4-
import { Calendar, MapPin, CalendarDays, Ticket } from 'lucide-react';
4+
import { Calendar, MapPin, CalendarDays, Ticket, HeartHandshake } from 'lucide-react';
55
import { useTranslation } from 'react-i18next';
66
import useScrollAnimation from '../hooks/useScrollAnimation';
77
import LazyImage from '../components/LazyImage';
@@ -41,6 +41,9 @@ const Home = () => {
4141
<Link to={l('/attend')} className="btn btn-secondary btn-lg">
4242
<Ticket size="1em" style={{ verticalAlign: '-0.125em' }} /> {t('home.getYourTicket')}
4343
</Link>
44+
<Link to={l('/attend/sponsor')} className="btn btn-primary btn-lg">
45+
<HeartHandshake size="1em" style={{ verticalAlign: '-0.125em' }} /> {t('home.supportAttendees')}
46+
</Link>
4447
</div>
4548
</div>
4649
</section>

src/pages/TicketSponsor.jsx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,26 @@ import { useEffect, useRef } from 'react';
22
import { useParams } from 'react-router-dom';
33
import { Composer, Formsmd } from 'formsmd';
44
import 'formsmd/dist/css/formsmd.min.css';
5-
import { ticketSponsorEndpoint, ticketSponsorSheetName, paymentMethods } from '../data/ticketSponsor';
5+
import { ticketSponsorEndpoint, ticketSponsorSheetName, paymentMethods, payTo, ticketPriceXAF } from '../data/ticketSponsor';
66
import '../styles/sponsor-form.css';
77

88
const copy = {
99
en: {
1010
title: 'Sponsor a Student',
1111
titleHighlight: 'Ticket',
1212
subtitle: 'Cover the cost of a ticket so a student can attend PyCon Cameroon 2026. Pay by MTN MoMo or Orange Money, then confirm your gift below so we can match it and thank you.',
13-
intro: '### Let us confirm your gift\nAnswer a few quick questions. Send your mobile money payment first, then have the confirmation code ready.',
13+
intro: '### Let us set up your gift\nAnswer a few quick questions about you, then you will make the payment and confirm it here.',
1414
name: 'First things first, how can we call you?',
1515
nameDesc: 'The name we should address you by.',
1616
emailGreeting: 'Thanks {$ fullName $}!',
1717
email: 'What email can we reach you on?',
1818
organisation: 'Are you giving on behalf of a company or organisation?',
1919
organisationDesc: 'Leave this blank to sponsor as an individual.',
2020
phone: 'What phone number can we reach you on?',
21-
ticketsGreeting: 'Here is the important part, {$ fullName $}.',
21+
ticketsGreeting: 'Almost there, {$ fullName $}.',
2222
tickets: 'How many student tickets would you like to sponsor?',
23+
payInstructions: (p, price) =>
24+
`### Now make the payment\nYou are sponsoring **{$ tickets $}** ticket(s) at **${price.toLocaleString('en-US')} FCFA** each. Please send **(number of tickets × ${price.toLocaleString('en-US')} FCFA) + mobile money charges** to **one** of these numbers, then come back to confirm:\n\n- **MTN MoMo:** ${p.mtn}\n- **Orange Money:** ${p.orange}\n\nBoth accounts are registered to **${p.name}**. Once your transfer is done, tap OK and we will record the confirmation.`,
2325
amount: 'How much did you send in total?',
2426
amountDesc: 'The total you paid by mobile money, in XAF.',
2527
method: 'Which service did you pay with?',
@@ -39,16 +41,18 @@ const copy = {
3941
title: 'Parrainez un billet',
4042
titleHighlight: 'étudiant',
4143
subtitle: "Prenez en charge un billet pour qu'un étudiant puisse participer à la PyCon Cameroun 2026. Payez par MTN MoMo ou Orange Money, puis confirmez votre don ci-dessous pour que nous puissions le rapprocher et vous remercier.",
42-
intro: '### Confirmons votre don\nRépondez à quelques questions rapides. Effectuez d\'abord votre paiement mobile money, puis gardez le code de confirmation à portée de main.',
44+
intro: '### Préparons votre don\nRépondez à quelques questions sur vous, puis vous effectuerez le paiement et le confirmerez ici.',
4345
name: 'Pour commencer, comment pouvons-nous vous appeler ?',
4446
nameDesc: 'Le nom sous lequel nous devons vous adresser.',
4547
emailGreeting: 'Merci {$ fullName $} !',
4648
email: 'À quelle adresse email pouvons-nous vous joindre ?',
4749
organisation: "Faites-vous ce don au nom d'une entreprise ou d'une organisation ?",
4850
organisationDesc: 'Laissez vide pour parrainer à titre individuel.',
4951
phone: 'Sur quel numéro de téléphone pouvons-nous vous joindre ?',
50-
ticketsGreeting: 'Voici le plus important, {$ fullName $}.',
52+
ticketsGreeting: 'Presque fini, {$ fullName $}.',
5153
tickets: 'Combien de billets étudiants souhaitez-vous parrainer ?',
54+
payInstructions: (p, price) =>
55+
`### Effectuez maintenant le paiement\nVous parrainez **{$ tickets $}** billet(s) à **${price.toLocaleString('fr-FR')} FCFA** chacun. Envoyez **(nombre de billets × ${price.toLocaleString('fr-FR')} FCFA) + les frais mobile money** à **l'un** de ces numéros, puis revenez confirmer :\n\n- **MTN MoMo :** ${p.mtn}\n- **Orange Money :** ${p.orange}\n\nLes deux comptes sont enregistrés au nom de **${p.name}**. Une fois le transfert effectué, appuyez sur OK et nous enregistrerons la confirmation.`,
5256
amount: 'Quel montant total avez-vous envoyé ?',
5357
amountDesc: 'Le total payé par mobile money, en XAF.',
5458
method: 'Avec quel service avez-vous payé ?',
@@ -114,11 +118,14 @@ function buildTemplate(lang) {
114118
composer.numberInput('tickets', { question: t.tickets, required: true, min: 1, max: 500, step: 1, value: 1 });
115119

116120
composer.slide();
117-
composer.numberInput('amountPaid', { question: t.amount, description: t.amountDesc, required: true, min: 100, step: 1, unitEnd: 'XAF' });
121+
composer.free(t.payInstructions(payTo, ticketPriceXAF));
118122

119123
composer.slide();
120124
composer.choiceInput('paymentMethod', { question: t.method, choices: paymentMethods, required: true });
121125

126+
composer.slide();
127+
composer.numberInput('amountPaid', { question: t.amount, description: t.amountDesc, required: true, min: 100, step: 1, unitEnd: 'XAF' });
128+
122129
composer.slide();
123130
composer.telInput('payerNumber', { question: t.payerNumber, description: t.payerNumberDesc, required: true, maxlength: 20 });
124131

0 commit comments

Comments
 (0)