From 1a6eb7e2ff0bf551e1560c67170e90fa8ec2a8ea Mon Sep 17 00:00:00 2001 From: Joe Carstairs <118172583+jcarstairs-scottlogic@users.noreply.github.com> Date: Thu, 25 Jan 2024 16:59:42 +0000 Subject: 33 / Pay annual subscription by PayPal (#68) * Refactors paypal-buttons -> paypal-product-buttons WebComponent * Pulls out address to data file * Defines annual subscription prices data hash * Styles paypal-product-buttons * Styles
* Details have cursor:pointer on the summary * Moves Jyne section to separate page * Rewrites payment options using details components * Reworks translation typing * Defines MembershipType enum * Adds translations for MembershipType enum * Can pay annual subs by PayPal * Styles tables better --- src/components/LallansIssue.astro | 4 +- src/components/Navbar/NavLinks.astro | 3 +- src/components/PayPalButtons.astro | 150 ---------------- src/components/PaypalProductButtons.astro | 26 +++ src/components/Scotsoun.astro | 4 +- src/data/contactDetails.ts | 16 ++ src/data/subscriptionPrices.ts | 7 + src/enums/MembershipType.ts | 42 +++++ src/i18n/translate.ts | 28 +-- src/i18n/translations/components/breadcrumbs.ts | 20 +++ src/i18n/translations/enums/membershipType.ts | 21 +++ src/i18n/translations/pages/home.ts | 76 --------- src/i18n/translations/pages/jyne.ts | 190 +++++++++++++++++++++ .../furthsettins/lallans/[issueNumber]/index.astro | 1 + .../furthsettins/scotsoun/[scotsounId]/index.astro | 1 + src/pages/[locale]/index.astro | 27 +-- src/pages/[locale]/jyne/index.astro | 104 +++++++++++ .../jyne/paypal/[membershipType]/index.astro | 41 +++++ .../jyne/paypal/[membershipType]/success.astro | 30 ++++ src/pages/[locale]/jyne/paypal/index.astro | 27 +++ src/scripts/wc/paypal-product-buttons.ts | 146 ++++++++++++++++ src/types/TranslationsDictionary.d.ts | 15 +- 22 files changed, 703 insertions(+), 276 deletions(-) delete mode 100644 src/components/PayPalButtons.astro create mode 100644 src/components/PaypalProductButtons.astro create mode 100644 src/data/subscriptionPrices.ts create mode 100644 src/enums/MembershipType.ts create mode 100644 src/i18n/translations/enums/membershipType.ts create mode 100644 src/i18n/translations/pages/jyne.ts create mode 100644 src/pages/[locale]/jyne/index.astro create mode 100644 src/pages/[locale]/jyne/paypal/[membershipType]/index.astro create mode 100644 src/pages/[locale]/jyne/paypal/[membershipType]/success.astro create mode 100644 src/pages/[locale]/jyne/paypal/index.astro create mode 100644 src/scripts/wc/paypal-product-buttons.ts (limited to 'src') diff --git a/src/components/LallansIssue.astro b/src/components/LallansIssue.astro index c8bc6eb..317ff2d 100644 --- a/src/components/LallansIssue.astro +++ b/src/components/LallansIssue.astro @@ -7,7 +7,7 @@ import type LallansIssue from '$types/LallansIssue'; import { Image } from 'astro:assets'; import LallansIssueContributions from './LallansIssueContributions.astro'; import LallansIssueContributors from './LallansIssueContributors.astro'; -import PayPalButtons from './PayPalButtons.astro'; +import PaypalProductButtons from './PaypalProductButtons.astro'; interface Props { issue: LallansIssue; @@ -27,7 +27,7 @@ const t = translate(locale);
- {t(tFurthsettins, { key: 'title' })}
  • - {t(tHame, { key: 'jyne' })} + {t(tJyne, { key: 'title' })}
  • {t(tHame, { key: 'contact' })} diff --git a/src/components/PayPalButtons.astro b/src/components/PayPalButtons.astro deleted file mode 100644 index cdea5cb..0000000 --- a/src/components/PayPalButtons.astro +++ /dev/null @@ -1,150 +0,0 @@ ---- -import env from '$lib/env'; -import type Price from '$types/Price'; - -interface Props { - successPageUrl: string; - productDescription: string; - shortDescription: string; - totalPrice: Price; -} - -const { successPageUrl, productDescription, shortDescription, totalPrice } = Astro.props; - -const PAYPAL_CLIENT_ID = - env.ENVIRONMENT === 'prod' ? env.PAYPAL_LIVE_CLIENT_ID : env.PAYPAL_SANDBOX_CLIENT_ID; ---- - - -
    -
    - - diff --git a/src/components/PaypalProductButtons.astro b/src/components/PaypalProductButtons.astro new file mode 100644 index 0000000..0ebbd3f --- /dev/null +++ b/src/components/PaypalProductButtons.astro @@ -0,0 +1,26 @@ +--- +import env from '$lib/env'; +import type Price from '$types/Price'; + +interface Props { + successPageUrl: string; + productDescription: string; + shortDescription: string; + totalPrice: Price; +} + +const { successPageUrl, productDescription, shortDescription, totalPrice } = Astro.props; + +const PAYPAL_CLIENT_ID = + env.ENVIRONMENT === 'prod' ? env.PAYPAL_LIVE_CLIENT_ID : env.PAYPAL_SANDBOX_CLIENT_ID; +--- + + + Loading PayPal buttons… + diff --git a/src/components/Scotsoun.astro b/src/components/Scotsoun.astro index cca330d..7acae8b 100644 --- a/src/components/Scotsoun.astro +++ b/src/components/Scotsoun.astro @@ -4,7 +4,7 @@ import translate from '$i18n/translate'; import tSite from '$i18n/translations/site'; import tComponent from '$i18n/translations/components/scotsoun'; import type Scotsoun from '$types/Scotsoun'; -import PayPalButtons from './PayPalButtons.astro'; +import PaypalProductButtons from './PaypalProductButtons.astro'; import relativePath from '$lib/relativePath'; import { getLocaleFromPathOrThrow } from '$lib/getLocaleFromPath'; @@ -27,7 +27,7 @@ const t = translate(locale);
    - = TranslationsDictionary<{ - [key in Key]: { [locale in typeof defaultLocale]: Translation } & { - [locale in Locale]?: Translation; - }; + [key in Key]: LocalesTranslationHash; }>; export default function (locale: Locale) { - return function < - Key extends string, - Params, - Dict extends TranslationsDictionaryWith, - >(dict: Dict, params: { key: Key } & { [Param in keyof Params]: string }) { + return function ( + dict: TranslationsDictionaryWith, + params: { key: Key } & ParamsHash + ) { if (!(params.key in dict)) { throw new Error(` Could not find translation for key '${params.key}'. Available keys were: @@ -26,7 +26,9 @@ export default function (locale: Locale) { .join(', ')} `); } - const translation = dict[params.key][locale] ?? dict[params.key][defaultLocale]; + const localesTranslationHash: LocalesTranslationHash = dict[params.key]; + const translation: Translation = + localesTranslationHash[locale] ?? localesTranslationHash[defaultLocale]; return translation(params); }; } diff --git a/src/i18n/translations/components/breadcrumbs.ts b/src/i18n/translations/components/breadcrumbs.ts index 5aeff0e..8e3d027 100644 --- a/src/i18n/translations/components/breadcrumbs.ts +++ b/src/i18n/translations/components/breadcrumbs.ts @@ -22,6 +22,26 @@ const tBreadcrumbs = { sco: () => 'Scotsoun', 'en-GB': () => 'Scotsoun', }, + '/jyne/': { + sco: () => 'Jyne', + 'en-GB': () => 'Join', + }, + '/jyne/paypal/': { + sco: () => 'PayPal', + 'en-GB': () => 'PayPal', + }, + '/jyne/paypal/individual-uk/': { + sco: () => 'Individual (UK)', + 'en-GB': () => 'Individual (UK)', + }, + '/jyne/paypal/individual-non-uk/': { + sco: () => 'Individual (non-UK)', + 'en-GB': () => 'Individual (non-UK)', + }, + '/jyne/paypal/institution-uk/': { + sco: () => 'Institutional (UK)', + 'en-GB': () => 'Institutional (UK)', + }, '/news/': { sco: () => 'News', 'en-GB': () => 'News', diff --git a/src/i18n/translations/enums/membershipType.ts b/src/i18n/translations/enums/membershipType.ts new file mode 100644 index 0000000..0e1db06 --- /dev/null +++ b/src/i18n/translations/enums/membershipType.ts @@ -0,0 +1,21 @@ +import type { TranslationsDictionary, LocalesTranslationHash } from '$types/TranslationsDictionary'; + +import MembershipType from '$enums/MembershipType'; + +const tEnum: { [key in MembershipType]: LocalesTranslationHash } = { + [MembershipType.IndividualUk]: { + sco: () => 'Individual (UK)', + 'en-GB': () => 'Individual (UK)', + }, + [MembershipType.IndividualNonUk]: { + sco: () => 'Individual (non-UK)', + 'en-GB': () => 'Individual (non-UK)', + }, + [MembershipType.InstitutionUk]: { + sco: () => 'Institutional (UK)', + 'en-GB': () => 'Institutional (UK)', + }, +}; + +type Raw = typeof tEnum; +export default tEnum as TranslationsDictionary; diff --git a/src/i18n/translations/pages/home.ts b/src/i18n/translations/pages/home.ts index b577a46..6628682 100644 --- a/src/i18n/translations/pages/home.ts +++ b/src/i18n/translations/pages/home.ts @@ -119,82 +119,6 @@ const tPage = { sco: () => 'Aw furthsettins', 'en-GB': () => 'All publications', }, - jyne: { - sco: () => 'Jyne', - 'en-GB': () => 'Join', - }, - 'why-jyne': { - sco: () => 'Why jyne the Scots Leid Associe?', - 'en-GB': () => 'Why join the Scots Language Society?', - }, - 'why-jyne-para-1': { - sco: () => ` - Bi jynin us, ye ar helpin us tae heize up the Scots leid, maistly bi giein - Scots scrievers a place tae lairn frae anither an finnd their ain Scots vyce. - `, - 'en-GB': () => ` - By joining us, you are helping us to champion the Scots language, - especially by giving Scots writers a place to learn from one - another and to find their own Scots voice. - `, - }, - 'why-jyne-para-2': { - sco: () => ` - Forby, memmers get biannual issues o our aesome Lallans magazine gratis, - an hae the richt tae atten our Annual Collogues, whaur we haud our AGM an - enjoy talks frae kenspeckle spikkers on thochtie maiters effeirin til Scots - leid an leiteratur. - `, - 'en-GB': () => ` - In addition, members get biannual issues of our unique Lallans - magazine gratis, and have the right to attend our Annual Conferences, where - we hold our AGM and enjoy talks from highly regarded speakers on - thought-provoking subjects relating to Scots language and literature. - `, - }, - 'why-jyne-para-3': { - sco: () => ` - Gin whit ye ar seekin is a community o prose-scrievers, makars, pleywreichts - an owersetters, aw wi muckle care fur the Scots leid, the ar nae peer wi hus, - the auldest Scots-leid activist organisation that’s about eenou an the anely - fully dedicatit til the forderance o new Scots leiteratur. - `, - 'en-GB': () => ` - If what you’re looking for is a community of prose-writers, poets, - playwrights and translators with a passion for the Scots language, we have - no equal. We are the oldest extant Scots-language activist organisation and - the only one solely dedicated to the development of new Scots literature. - `, - }, - 'hou-jyne': { - sco: () => 'Hou can A jyne?', - 'en-GB': () => 'How can I join?', - }, - 'hou-jyne-para-1': { - sco: () => ` - Fur individuals, memmership costs £20 per annum. Fur institutions, the stent is £25 per annum. - `, - 'en-GB': () => ` - For individuals, membership costs £20 per annum. For institutions, the fee is £25 per annum. - `, - }, - 'hou-jyne-para-2': { - sco: ({ membershipEmail }: { membershipEmail: string }) => ` - Fur tae become a memmer, simply get in titch wi us at - ${membershipEmail} - an we’ll provide ye wi our bank details; or ye can jyne bi sendin us a cheque - made peyable til The Scots Language Society. See - Contact us - fur our address. - `, - 'en-GB': ({ membershipEmail }: { membershipEmail: string }) => ` - To become a member, simply get in touch with us at - ${membershipEmail} - and we’ll provide you with our bank details; or you can join by sending us - a cheque made payable to The Scots Language Society. See - Contact us for our address. - `, - }, contact: { sco: () => 'Contact', 'en-GB': () => 'Contact', diff --git a/src/i18n/translations/pages/jyne.ts b/src/i18n/translations/pages/jyne.ts new file mode 100644 index 0000000..bbcc67c --- /dev/null +++ b/src/i18n/translations/pages/jyne.ts @@ -0,0 +1,190 @@ +import type { TranslationsDictionary } from '$types/TranslationsDictionary'; + +import MembershipType from '$enums/MembershipType'; +import { annualSubscriptionPrice } from '$data/subscriptionPrices'; +import tMembershipType from '$i18n/translations/enums/membershipType'; +import translate from '$i18n/translate'; + +const tPage = { + title: { + sco: () => 'Jyne', + 'en-GB': () => 'Join', + }, + 'why-jyne': { + sco: () => 'Why jyne the Scots Leid Associe?', + 'en-GB': () => 'Why join the Scots Language Society?', + }, + 'why-jyne-para-1': { + sco: () => ` + Bi jynin us, ye ar helpin us tae heize up the Scots leid, maistly bi giein + Scots scrievers a place tae lairn frae anither an finnd their ain Scots vyce. + `, + 'en-GB': () => ` + By joining us, you are helping us to champion the Scots language, + especially by giving Scots writers a place to learn from one + another and to find their own Scots voice. + `, + }, + 'why-jyne-para-2': { + sco: () => ` + Forby, memmers get biannual issues o our aesome Lallans magazine gratis, + an hae the richt tae atten our Annual Collogues, whaur we haud our AGM an + enjoy talks frae kenspeckle spikkers on thochtie maiters effeirin til Scots + leid an leiteratur. + `, + 'en-GB': () => ` + In addition, members get biannual issues of our unique Lallans + magazine gratis, and have the right to attend our Annual Conferences, where + we hold our AGM and enjoy talks from highly regarded speakers on + thought-provoking subjects relating to Scots language and literature. + `, + }, + 'why-jyne-para-3': { + sco: () => ` + Gin whit ye ar seekin is a community o prose-scrievers, makars, pleywreichts + an owersetters, aw wi muckle care fur the Scots leid, the ar nae peer wi hus, + the auldest Scots-leid activist organisation that’s about eenou an the anely + fully dedicatit til the forderance o new Scots leiteratur. + `, + 'en-GB': () => ` + If what you’re looking for is a community of prose-writers, poets, + playwrights and translators with a passion for the Scots language, we have + no equal. We are the oldest extant Scots-language activist organisation and + the only one solely dedicated to the development of new Scots literature. + `, + }, + 'hou-jyne': { + sco: () => 'Hou can A jyne?', + 'en-GB': () => 'How can I join?', + }, + 'hou-jyne-intro': { + sco: () => ` + For tae jyne, ye can pey by PayPal, bank transfer or cheque. The fee is + as ablo. + `, + 'en-GB': () => ` + To join, you can pay by PayPal, bank transfer or cheque. The fee is as below. + `, + }, + 'subscription-price-table-caption': { + sco: () => 'Annual subscription price per membership type', + 'en-GB': () => 'Annual subscription price per membership type', + }, + 'hou-pey-by-paypal-title': { + sco: () => 'PayPal', + 'en-GB': () => 'PayPal', + }, + 'hou-pey-by-paypal-para': { + sco: () => 'Select a membership type', + 'en-GB': () => 'Select a membership type', + }, + 'membership-type-individual-uk': { + sco: () => 'Ane year individual UK membership', + 'en-GB': () => 'One year individual UK membership', + }, + 'membership-type-individual-uk-para': { + sco: () => ` + Here, ye can pey for ane year’s annual subscription til the Scots Leid Associe + gin ye ar an individual and ye want yer copies o Lallans sent til + a UK address. This will cost + £${annualSubscriptionPrice[MembershipType.IndividualUk]}. Gin ye want + some ither kind o membership, + see the ither options. + `, + 'en-GB': () => ` + Here, you can pay for one year’s annual subscription to the Scots Language + Society if you are an individual and you want your copies of Lallans + sent to a UK address. This will cost + £${annualSubscriptionPrice[MembershipType.IndividualNonUk]}. If you want + some other kind of membership, + see the other options. + `, + }, + 'membership-type-individual-non-uk': { + sco: () => 'Ane year individual non-UK membership', + 'en-GB': () => 'One year individual non-UK membership', + }, + 'membership-type-individual-non-uk-para': { + sco: () => ` + Here, ye can pey for ane year’s annual subscription til the Scots Leid Associe + gin ye ar an individual an ye want yer copies o Lallans sent til + a non-UK address. This will cost + £${annualSubscriptionPrice[MembershipType.IndividualNonUk]}. Gin ye want + some ither kind o membership, + see the ither options. + `, + 'en-GB': () => ` + Here, you can pay for one year’s annual subscription to the Scots Language + Society if you are an individual and you want your copies of Lallans + sent to a non-UK address. This will cost + £${annualSubscriptionPrice[MembershipType.IndividualNonUk]}. If you want + some other kind of membership, + see the other options. + `, + }, + 'membership-type-institution-uk': { + sco: () => 'Ane year UK institutional membership', + 'en-GB': () => 'One year UK institutional membership', + }, + 'membership-type-institution-uk-para': { + sco: () => ` + Here, ye can pey for ane year’s annual subscription til the Scots Leid Associe + gin ye ar an institution. This will cost + £${annualSubscriptionPrice[MembershipType.InstitutionUk]}. Gin ye want + some ither kind o membership, + see the ither options. + `, + 'en-GB': () => ` + Here, you can pay for one year’s annual subscription to the Scots + Language Society if you are an institution based in the UK. This will + cost £${annualSubscriptionPrice[MembershipType.InstitutionUk]}. If you + want some other kind of membership, + see the other options. + `, + }, + 'hou-pey-by-bank-transfer-title': { + sco: () => 'Bank transfer', + 'en-GB': () => 'Bank transfer', + }, + 'hou-pey-by-bank-transfer-para': { + sco: ({ emailAddress }: { emailAddress: string }) => ` + Send us an email at ${emailAddress} an we’ll send ye oor bank details. + `, + 'en-GB': ({ emailAddress }: { emailAddress: string }) => ` + Send us an email at ${emailAddress} and we’ll send you our bank details. + `, + }, + 'hou-pey-by-cheque-title': { + sco: () => 'Cheque', + 'en-GB': () => 'Cheque', + }, + 'hou-pey-by-cheque-para': { + sco: ({ address }: { address: string[] }) => ` + Mak out a cheque til The Scots Language Society, syne send it til us at the follaein address: +
    ${address.join('
    ')}
    + `, + 'en-GB': ({ address }: { address: string[] }) => ` + Make out a cheque to The Scots Language Society, then send it to us at the following address: +
    ${address.join('
    ')}
    + `, + }, + success: { + sco: () => 'Successfullie bocht membership', + 'en-GB': () => 'Successfully bought membership', + }, + 'success-para': { + sco: ({ membershipType }: { membershipType: MembershipType }) => ` + Ye hae successfullie bocht ane year’s + ${translate('sco')(tMembershipType, { key: membershipType })} + membership. We shuid be in contact wi ye some time shuin. + `, + 'en-GB': ({ membershipType }: { membershipType: MembershipType }) => ` + You have successfully bought one year’s + ${translate('en-GB')(tMembershipType, { key: membershipType })} + membership. We should be in contact with you some time soon. + `, + }, +}; + +type Raw = typeof tPage; +export default tPage as TranslationsDictionary; diff --git a/src/pages/[locale]/furthsettins/lallans/[issueNumber]/index.astro b/src/pages/[locale]/furthsettins/lallans/[issueNumber]/index.astro index 48f1947..82fabf0 100644 --- a/src/pages/[locale]/furthsettins/lallans/[issueNumber]/index.astro +++ b/src/pages/[locale]/furthsettins/lallans/[issueNumber]/index.astro @@ -23,4 +23,5 @@ const issue = await getLallansIssue[issueNumber](); + diff --git a/src/pages/[locale]/furthsettins/scotsoun/[scotsounId]/index.astro b/src/pages/[locale]/furthsettins/scotsoun/[scotsounId]/index.astro index 90053fe..4244f70 100644 --- a/src/pages/[locale]/furthsettins/scotsoun/[scotsounId]/index.astro +++ b/src/pages/[locale]/furthsettins/scotsoun/[scotsounId]/index.astro @@ -24,4 +24,5 @@ const scotsoun = await getScotsoun[scotsounId](); + diff --git a/src/pages/[locale]/index.astro b/src/pages/[locale]/index.astro index e8b9cf0..d930c20 100644 --- a/src/pages/[locale]/index.astro +++ b/src/pages/[locale]/index.astro @@ -55,36 +55,11 @@ const mostRecentNewsItem = await getMostRecentNewsItem(locale); -
    -

    - -

    -

    -

    -

    - -

    -

    -

    -

    -

    {contactDetails.generalEnquiries.emailAddress} -
    - Scots Language Society
    - c/o 61 Cliffburn Road
    - Arbroath
    - Angus
    - DD11 5BA
    - United Kingdom
    -
    +
    ')} />

    diff --git a/src/pages/[locale]/jyne/index.astro b/src/pages/[locale]/jyne/index.astro new file mode 100644 index 0000000..7a1b4f6 --- /dev/null +++ b/src/pages/[locale]/jyne/index.astro @@ -0,0 +1,104 @@ +--- +import type Locale from '$types/Locale'; + +import { annualSubscriptionPrice } from '$data/subscriptionPrices'; +import contactDetails from '$data/contactDetails'; +import Page from '$layouts/Page.astro'; +import localeStaticPaths from '$lib/localeStaticPaths'; +import translate from '$i18n/translate'; +import tPage from '$i18n/translations/pages/jyne'; +import tMembershipType from '$i18n/translations/enums/membershipType'; +import { allMembershipTypes } from '$enums/MembershipType'; + +export async function getStaticPaths() { + return localeStaticPaths; +} + +const locale = Astro.params.locale as Locale; +const t = translate(locale); +--- + + +
    +

    +

    + +
    +

    +

    + + + + + + { + allMembershipTypes.map((membershipType) => ( + + )) + } + + + + + + { + allMembershipTypes.map((membershipType) => ( + + )) + } + + +
    {t(tPage, { key: 'subscription-price-table-caption' })}
    {t(tMembershipType, { key: membershipType })}
    + {new Intl.NumberFormat('en-GB', { + style: 'currency', + currency: 'GBP', + minimumFractionDigits: 2, + maximumFractionDigits: 2, + }).format(annualSubscriptionPrice[membershipType])} +
    + +

    +

    + +
    +

    +

    +

    +

    +

    +
    diff --git a/src/pages/[locale]/jyne/paypal/[membershipType]/index.astro b/src/pages/[locale]/jyne/paypal/[membershipType]/index.astro new file mode 100644 index 0000000..0934854 --- /dev/null +++ b/src/pages/[locale]/jyne/paypal/[membershipType]/index.astro @@ -0,0 +1,41 @@ +--- +import type Locale from '$types/Locale'; +import { + type MembershipTypeSnakeCase, + allMembershipTypesSnakeCase, + snakeCaseToMembershipType, +} from '$enums/MembershipType'; +import { annualSubscriptionPrice } from '$data/subscriptionPrices'; +import Page from '$layouts/Page.astro'; +import PaypalProductButtons from '$components/PaypalProductButtons.astro'; +import localeStaticPaths from '$lib/localeStaticPaths'; +import translate from '$i18n/translate'; +import tJyne from '$i18n/translations/pages/jyne'; + +export async function getStaticPaths() { + return allMembershipTypesSnakeCase.flatMap((membershipType) => + localeStaticPaths.map((p) => ({ ...p, params: { ...p.params, membershipType } })) + ); +} + +const locale = Astro.params.locale as Locale; +const t = translate(locale); + +const membershipType = Astro.params.membershipType as MembershipTypeSnakeCase; +--- + + +
    +

    {t(tJyne, { key: `membership-type-${membershipType}` })}

    + +

    + + + +

    +
    diff --git a/src/pages/[locale]/jyne/paypal/[membershipType]/success.astro b/src/pages/[locale]/jyne/paypal/[membershipType]/success.astro new file mode 100644 index 0000000..569e294 --- /dev/null +++ b/src/pages/[locale]/jyne/paypal/[membershipType]/success.astro @@ -0,0 +1,30 @@ +--- +import type Locale from '$types/Locale'; +import { type MembershipTypeSnakeCase } from '$enums/MembershipType'; + +import Page from '$layouts/Page.astro'; +import { allMembershipTypesSnakeCase, snakeCaseToMembershipType } from '$enums/MembershipType'; +import localeStaticPaths from '$lib/localeStaticPaths'; +import translate from '$i18n/translate'; +import tJyne from '$i18n/translations/pages/jyne'; + +export async function getStaticPaths() { + return allMembershipTypesSnakeCase.flatMap((membershipType) => + localeStaticPaths.map((p) => ({ ...p, params: { ...p.params, membershipType } })) + ); +} + +const locale = Astro.params.locale as Locale; +const t = translate(locale); + +const membershipTypeSnakeCase = Astro.params.membershipType as MembershipTypeSnakeCase; +const membershipType = snakeCaseToMembershipType(membershipTypeSnakeCase); +--- + + +
    +

    {t(tJyne, { key: 'success' })}

    + +

    +

    +
    diff --git a/src/pages/[locale]/jyne/paypal/index.astro b/src/pages/[locale]/jyne/paypal/index.astro new file mode 100644 index 0000000..55905d1 --- /dev/null +++ b/src/pages/[locale]/jyne/paypal/index.astro @@ -0,0 +1,27 @@ +--- +import type Locale from '$types/Locale'; + +import Page from '$layouts/Page.astro'; +import localeStaticPaths from '$lib/localeStaticPaths'; +import translate from '$i18n/translate'; +import tJyne from '$i18n/translations/pages/jyne'; + +export async function getStaticPaths() { + return localeStaticPaths; +} + +const locale = Astro.params.locale as Locale; +const t = translate(locale); +--- + + +
    +

    +

    +

    +

    +
    diff --git a/src/scripts/wc/paypal-product-buttons.ts b/src/scripts/wc/paypal-product-buttons.ts new file mode 100644 index 0000000..ca06524 --- /dev/null +++ b/src/scripts/wc/paypal-product-buttons.ts @@ -0,0 +1,146 @@ +import { type PayPalNamespace, loadScript } from '@paypal/paypal-js'; + +const backendUrl = '/api'; + +class PaypalProductButtons extends HTMLElement { + constructor() { + super(); + + try { + const paypalClientId = this.getAttribute('paypal-client-id'); + + const paypalOptions = { + clientId: paypalClientId, + locale: 'en_GB', + commit: false, + currency: 'GBP', + intent: 'capture', + }; + + loadScript(paypalOptions) + .catch((err) => { + this.innerHTML = ` +
    + Failed to load PayPal buttons +

    ${err}

    +
    + `; + console.error(`Failed to load the PayPal JS SDK script. ${err}`); + }) + .then((paypal) => { + const constructButtons = paypal?.Buttons; + if (paypal && constructButtons) { + const successPageUrl = this.getAttribute('success-page-url'); + this.innerHTML = ''; + const div = document.createElement('div'); + this.appendChild(div); + this.makePaypalButtons(constructButtons, successPageUrl).render(div); + } + }) + .catch((err) => { + this.innerHTML = ` +
    + Failed to load PayPal buttons +

    ${err}

    +
    + `; + console.error(`Failed to construct the PayPal buttons. ${err}`); + }); + } catch (err) { + this.innerHTML = ` +
    + Failed to load PayPal buttons +

    ${err}

    +
    + `; + } + } + + makePaypalButtons( + constructButtons: Required['Buttons'], + successPageUrl: string + ) { + const productDescription = this.getAttribute('product-description'); + const shortDescription = this.getAttribute('short-description'); + const totalPrice = this.getAttribute('total-price'); + + return constructButtons({ + // This function is called to set up the transaction details without actually carrying it out + async createOrder() { + const body = JSON.stringify({ + productDescription, + shortDescription, + totalPrice, + }); + const headers = { + 'Content-Type': 'application/json', + }; + + let response: Response; + try { + response = await fetch(`${backendUrl}/order`, { method: 'POST', body, headers }); + } catch (err) { + throw new Error(`Failed to create order. ${err}`); + } + + if (!response.ok) { + throw new Error(` + Failed to create order. Backend response was + ${response.status} ${response.statusText}. ${await response.text()} + `); + } + + const { orderId, approvalLink } = await response.json(); + console.info(` + Successfully created order with ID + ${orderId}. Approval link: ${approvalLink} + `); + return orderId; + }, + + // This function is called after payment is confirmed + async onApprove(data) { + const body = JSON.stringify({ + id: data.orderID, + isApproved: true, + }); + const headers = { + 'Content-Type': 'application/json', + }; + + let response: Response; + try { + response = await fetch(`${backendUrl}/order`, { method: 'PATCH', body, headers }); + } catch (err) { + throw new Error(`Failed to capture order. ${err}`); + } + + if (!response.ok) { + throw new Error(` + Failed to capture order. Backend response was ${response.status} + ${response.statusText}. ${await response.text()} + `); + } + + const { orderId, requestStatus } = await response.json(); + console.info(` + Successfully captured order with ID ${orderId}, + request status is ${requestStatus}. + `); + + console.info(`Redirecting to confirmation page, ${successPageUrl}...`); + window.location.href = successPageUrl; + }, + }); + } + + getAttribute(key: string): string { + const value = super.getAttribute(key); + if (!value || typeof value !== 'string') { + throw new Error(`${key} attribute not provided to PaypalProductButtons component.`); + } + return value; + } +} + +customElements.define('paypal-product-buttons', PaypalProductButtons); diff --git a/src/types/TranslationsDictionary.d.ts b/src/types/TranslationsDictionary.d.ts index 5033ecd..47ee7f4 100644 --- a/src/types/TranslationsDictionary.d.ts +++ b/src/types/TranslationsDictionary.d.ts @@ -1,12 +1,15 @@ import type { defaultLocale } from '$i18n/locales'; import type Locale from './Locale'; -export type Translation = (params: { [key in keyof Params]: string }) => string; +export type Translation = (params: ParamsHash) => string; +export type LocalesTranslationHash = { + [locale in Locale]?: Translation; +} & { + [locale in typeof defaultLocale]: Translation; +}; export type TranslationsDictionary = { - readonly [key in keyof Raw]: { - [locale in Locale]?: Translation[0]>; - } & { - [locale in typeof defaultLocale]: Translation[0]>; - }; + readonly [key in keyof Raw]: LocalesTranslationHash< + Parameters[0] + >; }; -- cgit v1.2.3 From 87a291cc6b79610cc48e804fb94e6ab558a05528 Mon Sep 17 00:00:00 2001 From: Joe Carstairs Date: Fri, 26 Jan 2024 15:46:42 +0000 Subject: Lallans gallery splashes most recent issue only --- src/components/LallansIssuesGallery.astro | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/components/LallansIssuesGallery.astro b/src/components/LallansIssuesGallery.astro index 3e79de9..f4c8e16 100644 --- a/src/components/LallansIssuesGallery.astro +++ b/src/components/LallansIssuesGallery.astro @@ -10,19 +10,37 @@ const issues = (await getAllLallansIssues()).sort(issueNumberDescending); function issueNumberDescending(issue1: LallansIssue, issue2: LallansIssue) { return issue2.issueNumber - issue1.issueNumber; } + +const mostRecentIssue = issues[0]; +const allOtherIssues = issues.slice(1); --- -