Skip to content

Commit

Permalink
refactor(website): update donation payment flow
Browse files Browse the repository at this point in the history
  • Loading branch information
mkue committed Nov 14, 2023
1 parent 2bac9af commit e6d4067
Show file tree
Hide file tree
Showing 31 changed files with 565 additions and 288 deletions.
35 changes: 35 additions & 0 deletions shared/locales/de/website-donate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"amount-currency": "{{ amount, currency }}",
"title": "Was ist dein durchschnittliches monatliches Einkommen?",
"how-to-pay": "Wie möchtest du bezahlen?",
"amount": "Betrag",
"button-text": "Einen Unterschied machen",
"donation-impact": {
"monthly-contribution": "Dein monatlicher Beitrag:",
"direct-payout": "Dein Beitrag wird direkt auf das Mobiltelefon der Social Income Empfänger:innen ausgezahlt.",
"your-impact": "Dein Einfluss:",
"0": "{{ amount, currency }} legt den Grundstein für eine bedeutende Sache. Es ermöglicht uns, einer Person in Not ein Social Income zu bieten.",
"1": "{{ amount, currency }} deckt mehr als ein Drittel eines Social Incomes für eine bedürftige Person.",
"2": "{{ amount, currency }} finanziert mehr als die Hälfte eines Social Incomes für eine Person.",
"3": "Großartig! Dein monatlicher Beitrag von {{ amount, currency }} ermöglicht es mindestens einer bedürftigen Person ein vollständiges Social Income bereitzustellen.",
"4": "{{ amount, currency }} ermöglicht ein Social Income für mehr als zwei bedürftige Personen.",
"5": "Wunderbar! Dein Beitrag von {{ amount, currency }} finanziert ein Social Income für mehr als drei bedürftige Personen.",
"6": "Dein Beitrag von {{ amount, currency }} sichert ein Social Income für mehr als vier bedürftige Personen.",
"7": "Dein Beitrag von {{ amount, currency }} sichert ein Social Income für mehr als fünf bedürftige Personen.",
"8": "Dein monatlicher Beitrag von {{ amount, currency }} ist außergewöhnlich, ebenso wie dein Einfluss."
},
"donation-interval": {
"1": {
"title": "Monatlich",
"text": "{{ amount, currency }} jeden Monat zahlen"
},
"3": {
"title": "Quartalsweise",
"text": "{{ amount, currency }} alle 3 Monate zahlen"
},
"12": {
"title": "Jährlich",
"text": "{{ amount, currency }} jedes Jahr zahlen"
}
}
}
17 changes: 9 additions & 8 deletions shared/locales/de/website-me.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,23 @@
}
},
"contributions": {
"amount": "Amount",
"date": "Date",
"source": "Source",
"amount": "Betrag",
"date": "Datum",
"source": "Quelle",
"total": "Total",
"one-time-payment": "Neue einmalige Spende",
"amount-currency": "{{ amount, currency }}",
"sources": {
"benevity": "Benevity",
"cash": "Cash",
"cash": "Bar",
"stripe": "Stripe",
"wire-transfer": "Wire Transfer"
"wire-transfer": "Banküberweisung"
}
},
"subscriptions": {
"amount": "Amount",
"date": "Date",
"source": "Source",
"amount": "Betrag",
"date": "Datum",
"source": "Quelle",
"total": "Total",
"amount-currency": "{{ amount, currency }}",
"interval": "Interval",
Expand Down
35 changes: 35 additions & 0 deletions shared/locales/en/website-donate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"amount-currency": "{{ amount, currency }}",
"title": "What's your average monthly income?",
"how-to-pay": "How would you like to pay?",
"amount": "Amount",
"button-text": "Make a Difference",
"donation-impact": {
"monthly-contribution": "Your monthly contribution:",
"direct-payout": "The people in need receive your contribution directly on their mobile phones.",
"your-impact": "Your impact:",
"0": "{{ amount, currency }} lays the groundwork for a significant cause. It enables us to provide a Social Income to an individual facing hardship.",
"1": "{{ amount, currency }} pays for more than a third of a Social Income for one person in need.",
"2": "{{ amount, currency }} funds more than half of someone’s Social Income.",
"3": "Great! Your monthly contribution of {{ amount, currency }} will allow at least one person in need to receive a full Social Income.",
"4": "{{ amount, currency }} provides a Social Income for more than two people in need.",
"5": "Wonderful! Your contribution of {{ amount, currency }} funds a Social Income for more than three people in need.",
"6": "Your contribution of {{ amount, currency }} sustains a Social Income for more than four people in need.",
"7": "Your contribution of {{ amount, currency }} sustains a Social Income for more than five people in need.",
"8": "Your monthly contribution of {{ amount, currency }} is extraordinary, as well as your impact."
},
"donation-interval": {
"1": {
"title": "Monthly",
"text": "Pay {{ amount, currency }} every month"
},
"3": {
"title": "Quarterly",
"text": "Pay {{ amount, currency }} every 3 months"
},
"12": {
"title": "Yearly",
"text": "Pay {{ amount, currency }} every year"
}
}
}
1 change: 1 addition & 0 deletions shared/locales/en/website-me.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"date": "Date",
"source": "Source",
"total": "Total",
"one-time-payment": "New one-time donation",
"amount-currency": "{{ amount, currency }}",
"sources": {
"benevity": "Benevity",
Expand Down
22 changes: 10 additions & 12 deletions shared/src/firebase/client/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,16 @@ interface InitializeFirebaseClientProps {
functionsEmulatorPort?: number;
}

export const initializeFirebaseClient = (
{
firebaseConfig,
authEmulatorUrl,
firestoreEmulatorHost,
firestoreEmulatorPort,
storageEmulatorHost,
storageEmulatorPort,
functionsEmulatorHost,
functionsEmulatorPort,
}: InitializeFirebaseClientProps,
) => {
export const initializeFirebaseClient = ({
firebaseConfig,
authEmulatorUrl,
firestoreEmulatorHost,
firestoreEmulatorPort,
storageEmulatorHost,
storageEmulatorPort,
functionsEmulatorHost,
functionsEmulatorPort,
}: InitializeFirebaseClientProps) => {
const app = getOrInitializeFirebaseClientApp(firebaseConfig);
const auth = getAuth(app);
const functions = getFunctions(app, DEFAULT_REGION);
Expand Down
12 changes: 9 additions & 3 deletions shared/src/utils/messaging/email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@ interface SendEmailProps {
password: string;
}

export const sendEmail = async (
{ from = '[email protected]', to, subject, content, attachments = [], user, password }: SendEmailProps,
) => {
export const sendEmail = async ({
from = '[email protected]',
to,
subject,
content,
attachments = [],
user,
password,
}: SendEmailProps) => {
let transporter: Transporter;
if (!user) {
const testAccount = await nodemailer.createTestAccount();
Expand Down
9 changes: 6 additions & 3 deletions shared/src/utils/messaging/whatsapp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ export interface SendWhatsappProps {
templateProps: RenderTemplateProps;
}

export const sendWhatsapp = async (
{ to, from, twilioConfig, templateProps }: SendWhatsappProps,
): Promise<MessageInstance> => {
export const sendWhatsapp = async ({
to,
from,
twilioConfig,
templateProps,
}: SendWhatsappProps): Promise<MessageInstance> => {
const client = new Twilio(twilioConfig.sid, twilioConfig.token);
const body = await renderTemplate(templateProps);
return client.messages.create({ body: body, from: `whatsapp:${from}`, to: `whatsapp:${to}` });
Expand Down
9 changes: 6 additions & 3 deletions shared/src/utils/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ const partials = [
];
partials.forEach((partial) => Handlebars.registerPartial(partial.name, readHbs(partial.path)));

export const renderTemplate = async (
{ language, translationNamespace = [], hbsTemplatePath, context }: RenderTemplateProps,
) => {
export const renderTemplate = async ({
language,
translationNamespace = [],
hbsTemplatePath,
context,
}: RenderTemplateProps) => {
const i18n = i18next.createInstance();
await i18n
.use(
Expand Down
8 changes: 5 additions & 3 deletions ui/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@ UI elements:
**Example**:

```tsx
export const SoExampleComponent = (
{ children, exampleProperty, ...props }: SoExampleComponentProps,
) => {
export const SoExampleComponent = ({
children,
exampleProperty,
...props
}: SoExampleComponentProps) => {
return (
<p example-property={exampleProperty} {...props}>
{children}
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
const Comp = asChild ? Slot : 'button';
return (
<Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props}>
{Icon && <Icon className={cn('h-4 w-4', { 'mr-2': size !== 'icon' })} />}
{Icon && <Icon className={cn('h-4 w-4', { 'mr-2': size !== 'icon', 'h-6 w-6': size === 'lg' })} />}
{children}
</Comp>
);
Expand Down
11 changes: 8 additions & 3 deletions ui/src/components/carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ type CarouselProps = {
showControls?: boolean;
} & React.HTMLAttributes<HTMLDivElement>;

export const Carousel = (
{ children, className, options = {}, showDots = false, showControls = false, ...props }: CarouselProps,
) => {
export const Carousel = ({
children,
className,
options = {},
showDots = false,
showControls = false,
...props
}: CarouselProps) => {
const [emblaRef, emblaApi] = useEmblaCarousel(
options,
options?.autoPlay?.enabled ? [Autoplay(options.autoPlay)] : [],
Expand Down
6 changes: 3 additions & 3 deletions ui/src/components/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFi
const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>(
{ ...props }: ControllerProps<TFieldValues, TName>,
) => {
>({
...props
}: ControllerProps<TFieldValues, TName>) => {
return (
<FormFieldContext.Provider value={{ name: props.name }}>
<Controller {...props} />
Expand Down
26 changes: 13 additions & 13 deletions ui/src/components/typography/typography.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const FONT_COLOR_MAP: { [key in FontColor]: string } = {
'destructive-foreground': 'text-destructive-foreground',
muted: 'text-muted',
'muted-foreground': 'text-muted-foreground',
card: 'text-card',
'card-foreground': 'text-card-foreground',
popover: 'text-popover',
'popover-foreground': 'text-popover-foreground',
};
Expand All @@ -66,26 +68,24 @@ export type TypographyProps<C extends ElementType> = {
lineHeight?: LineHeight;
} & ComponentPropsWithoutRef<C>;

export function Typography<C extends ElementType = 'p'>(
{
as,
size = 'md',
weight = 'normal',
color = 'foreground',
lineHeight = 'normal',
className,
children,
...props
}: TypographyProps<C>,
) {
export function Typography<C extends ElementType = 'p'>({
as,
size = 'md',
weight = 'normal',
color = undefined,
lineHeight = 'normal',
className,
children,
...props
}: TypographyProps<C>) {
const Component = as || 'p';
return (
<Component
className={twMerge(
classNames(
FONT_SIZE_MAP[size],
FONT_WEIGHT_MAP[weight],
FONT_COLOR_MAP[color],
FONT_COLOR_MAP[color] || '',
LINE_HEIGHT_MAP[lineHeight],
className,
),
Expand Down
3 changes: 3 additions & 0 deletions ui/src/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@
--background: hsl(216, 54%, 55%);
--foreground: hsl(60 9.1% 97.8%);

--card: hsl(216, 54%, 95%);
--card-foreground: hsl(0, 0%, 10%);

--primary: hsl(48, 100%, 49%);
--primary-foreground: hsl(0, 0%, 20%);
}
Expand Down
2 changes: 2 additions & 0 deletions ui/src/interfaces/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export type FontColor = Extract<
| 'muted-foreground'
| 'accent'
| 'accent-foreground'
| 'card'
| 'card-foreground'
| 'popover'
| 'popover-foreground'
>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default function Section1Form({ translations, lang, region }: Section1Inp
});

const onSubmit = (values: FormSchema) => {
router.push(`/donate/individual?amount=${(Number(values.amount) / 100).toFixed(2)}`);
router.push(`/${lang}/${region}/donate/individual?amount=${Number(values.amount).toFixed(0)}`);
};

return (
Expand All @@ -51,7 +51,7 @@ export default function Section1Form({ translations, lang, region }: Section1Inp
control={form.control}
name="amount"
render={({ field }) => (
<FormItem className="sm:basis-2/3">
<FormItem className="flex-1">
<FormControl>
<Input className="h-16 text-lg" placeholder={translations.amount} {...field} />
</FormControl>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ const groups: Group[] = [
export default async function Team({ params }: DefaultPageProps) {
const translator = await Translator.getInstance({ language: params.lang, namespaces: ['countries', 'website-team'] });
return (
<BaseContainer className="py-8">
<BaseContainer id="team" className="py-8">
<Typography as="h3" size="xl" color="muted-foreground" className="mb-4">
{translator.t('header')}
</Typography>
Expand Down
17 changes: 13 additions & 4 deletions website/src/app/[lang]/[region]/(website)/me/payments/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
import { DefaultPageProps } from '@/app/[lang]/[region]';
import { ContributionsTable } from '@/app/[lang]/[region]/(website)/me/payments/contributions-table';
import { PlusCircleIcon } from '@heroicons/react/24/outline';
import { Translator } from '@socialincome/shared/src/utils/i18n';
import { Button } from '@socialincome/ui';
import Link from 'next/link';

export default async function Page({ params }: DefaultPageProps) {
const translator = await Translator.getInstance({ language: params.lang, namespaces: ['website-me'] });
export default async function Page({ params: { lang, region } }: DefaultPageProps) {
const translator = await Translator.getInstance({ language: lang, namespaces: ['website-me'] });

return (
<div className="grid grid-cols-1 gap-4">
<div className="flex flex-col">
<ContributionsTable
lang={lang}
region={region}
translations={{
date: translator.t('contributions.date'),
amount: translator.t('contributions.amount'),
source: translator.t('contributions.source'),
}}
{...params}
/>
<Link href={`/${lang}/${region}/donate/one-time`}>
<Button Icon={PlusCircleIcon} variant="ghost" size="lg" className="w-full">
{translator.t('contributions.one-time-payment')}
</Button>
</Link>
</div>
);
}
Loading

0 comments on commit e6d4067

Please sign in to comment.