From 5cb7eb6b8c71839717e008854173e8b70625c255 Mon Sep 17 00:00:00 2001 From: mkue Date: Fri, 1 Dec 2023 11:09:17 +0100 Subject: [PATCH] refactor(website): minor bugfixes and improvements --- package-lock.json | 31 ++ shared/locales/de/website-donate.json | 3 +- shared/locales/en/website-donate.json | 1 + shared/src/types/country.ts | 506 +++++++++--------- shared/src/types/currency.ts | 13 +- ui/src/components/checkbox.tsx | 27 + ui/src/index.ts | 1 + website/package.json | 1 + .../[region]/(website)/(home)/section-2.tsx | 2 +- .../[region]/(website)/login/login-form.tsx | 1 + .../our-work/(sections)/our-work.tsx | 2 +- .../donate/success/stripe/[session]/page.tsx | 1 + .../success/stripe/[session]/success-form.tsx | 20 +- website/src/components/footer/footer.tsx | 1 - website/src/components/vimeo-video.tsx | 12 +- website/src/i18n.ts | 13 +- website/src/middleware.ts | 6 +- 17 files changed, 362 insertions(+), 279 deletions(-) create mode 100644 ui/src/components/checkbox.tsx diff --git a/package-lock.json b/package-lock.json index 49ea2262e..252e05a15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7076,6 +7076,36 @@ } } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.4.tgz", + "integrity": "sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-use-size": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collapsible": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz", @@ -37412,6 +37442,7 @@ "dependencies": { "@heroicons/react": "^2.0.18", "@icons-pack/react-simple-icons": "^9.1.0", + "@radix-ui/react-checkbox": "^1.0.4", "@socialincome/shared": "^1.0.0", "@socialincome/ui": "^1.0.0", "@tanstack/react-query": "^5.8.4", diff --git a/shared/locales/de/website-donate.json b/shared/locales/de/website-donate.json index 3c59cc829..da6050fa9 100644 --- a/shared/locales/de/website-donate.json +++ b/shared/locales/de/website-donate.json @@ -47,8 +47,9 @@ "lastname": "Nachname", "email": "E-Mail", "country": "Land", - "gender": "Anrede", + "gender": "Geschlecht", "referral": "Wie hast du von uns erfahren?", + "accept-terms-and-conditions": "Ich akzeptiere die Teilnahmebedingungen und die Datenschutzrichtlinie.", "referrals": { "familyfriends": "Familie oder Freunde", "socialmedia": "Social Media", diff --git a/shared/locales/en/website-donate.json b/shared/locales/en/website-donate.json index 3a221d431..eff037c5f 100644 --- a/shared/locales/en/website-donate.json +++ b/shared/locales/en/website-donate.json @@ -49,6 +49,7 @@ "country": "Country", "gender": "Gender", "referral": "How did you hear about us?", + "accept-terms-and-conditions": "I accept the Terms and Conditions and Privacy Policy.", "referrals": { "familyfriends": "Family & Friends", "socialmedia": "Social Media", diff --git a/shared/src/types/country.ts b/shared/src/types/country.ts index 472c71162..347c12674 100644 --- a/shared/src/types/country.ts +++ b/shared/src/types/country.ts @@ -1,254 +1,252 @@ -const COUNTRIES = { - AF: 'Afghanistan', - AX: 'Åland Islands', - AL: 'Albania', - DZ: 'Algeria', - AS: 'American Samoa', - AD: 'Andorra', - AO: 'Angola', - AI: 'Anguilla', - AQ: 'Antarctica', - AG: 'Antigua and Barbuda', - AR: 'Argentina', - AM: 'Armenia', - AW: 'Aruba', - AU: 'Australia', - AT: 'Austria', - AZ: 'Azerbaijan', - BS: 'Bahamas', - BH: 'Bahrain', - BD: 'Bangladesh', - BB: 'Barbados', - BY: 'Belarus', - BE: 'Belgium', - BZ: 'Belize', - BJ: 'Benin', - BM: 'Bermuda', - BT: 'Bhutan', - BO: 'Bolivia, Plurinational State of', - BQ: 'Bonaire, Sint Eustatius and Saba', - BA: 'Bosnia and Herzegovina', - BW: 'Botswana', - BV: 'Bouvet Island', - BR: 'Brazil', - IO: 'British Indian Ocean Territory', - BN: 'Brunei Darussalam', - BG: 'Bulgaria', - BF: 'Burkina Faso', - BI: 'Burundi', - KH: 'Cambodia', - CM: 'Cameroon', - CA: 'Canada', - CV: 'Cape Verde', - KY: 'Cayman Islands', - CF: 'Central African Republic', - TD: 'Chad', - CL: 'Chile', - CN: 'China', - CX: 'Christmas Island', - CC: 'Cocos (Keeling) Islands', - CO: 'Colombia', - KM: 'Comoros', - CG: 'Congo', - CD: 'Congo, the Democratic Republic of the', - CK: 'Cook Islands', - CR: 'Costa Rica', - CI: "Côte d'Ivoire", - HR: 'Croatia', - CU: 'Cuba', - CW: 'Curaçao', - CY: 'Cyprus', - CZ: 'Czech Republic', - DK: 'Denmark', - DJ: 'Djibouti', - DM: 'Dominica', - DO: 'Dominican Republic', - EC: 'Ecuador', - EG: 'Egypt', - SV: 'El Salvador', - GQ: 'Equatorial Guinea', - ER: 'Eritrea', - EE: 'Estonia', - ET: 'Ethiopia', - FK: 'Falkland Islands (Malvinas)', - FO: 'Faroe Islands', - FJ: 'Fiji', - FI: 'Finland', - FR: 'France', - GF: 'French Guiana', - PF: 'French Polynesia', - TF: 'French Southern Territories', - GA: 'Gabon', - GM: 'Gambia', - GE: 'Georgia', - DE: 'Germany', - GH: 'Ghana', - GI: 'Gibraltar', - GR: 'Greece', - GL: 'Greenland', - GD: 'Grenada', - GP: 'Guadeloupe', - GU: 'Guam', - GT: 'Guatemala', - GG: 'Guernsey', - GN: 'Guinea', - GW: 'Guinea-Bissau', - GY: 'Guyana', - HT: 'Haiti', - HM: 'Heard Island and McDonald Islands', - VA: 'Holy See (Vatican City State)', - HN: 'Honduras', - HK: 'Hong Kong', - HU: 'Hungary', - IS: 'Iceland', - IN: 'India', - ID: 'Indonesia', - IR: 'Iran, Islamic Republic of', - IQ: 'Iraq', - IE: 'Ireland', - IM: 'Isle of Man', - IL: 'Israel', - IT: 'Italy', - JM: 'Jamaica', - JP: 'Japan', - JE: 'Jersey', - JO: 'Jordan', - KZ: 'Kazakhstan', - KE: 'Kenya', - KI: 'Kiribati', - KP: "Korea, Democratic People's Republic of", - KR: 'Korea, Republic of', - KW: 'Kuwait', - KG: 'Kyrgyzstan', - LA: "Lao People's Democratic Republic", - LV: 'Latvia', - LB: 'Lebanon', - LS: 'Lesotho', - LR: 'Liberia', - LY: 'Libya', - LI: 'Liechtenstein', - LT: 'Lithuania', - LU: 'Luxembourg', - MO: 'Macao', - MK: 'Macedonia, the Former Yugoslav Republic of', - MG: 'Madagascar', - MW: 'Malawi', - MY: 'Malaysia', - MV: 'Maldives', - ML: 'Mali', - MT: 'Malta', - MH: 'Marshall Islands', - MQ: 'Martinique', - MR: 'Mauritania', - MU: 'Mauritius', - YT: 'Mayotte', - MX: 'Mexico', - FM: 'Micronesia, Federated States of', - MD: 'Moldova, Republic of', - MC: 'Monaco', - MN: 'Mongolia', - ME: 'Montenegro', - MS: 'Montserrat', - MA: 'Morocco', - MZ: 'Mozambique', - MM: 'Myanmar', - NA: 'Namibia', - NR: 'Nauru', - NP: 'Nepal', - NL: 'Netherlands', - NC: 'New Caledonia', - NZ: 'New Zealand', - NI: 'Nicaragua', - NE: 'Niger', - NG: 'Nigeria', - NU: 'Niue', - NF: 'Norfolk Island', - MP: 'Northern Mariana Islands', - NO: 'Norway', - OM: 'Oman', - PK: 'Pakistan', - PW: 'Palau', - PS: 'Palestine, State of', - PA: 'Panama', - PG: 'Papua New Guinea', - PY: 'Paraguay', - PE: 'Peru', - PH: 'Philippines', - PN: 'Pitcairn', - PL: 'Poland', - PT: 'Portugal', - PR: 'Puerto Rico', - QA: 'Qatar', - RE: 'Réunion', - RO: 'Romania', - RU: 'Russian Federation', - RW: 'Rwanda', - BL: 'Saint Barthélemy', - SH: 'Saint Helena, Ascension and Tristan da Cunha', - KN: 'Saint Kitts and Nevis', - LC: 'Saint Lucia', - MF: 'Saint Martin (French part)', - PM: 'Saint Pierre and Miquelon', - VC: 'Saint Vincent and the Grenadines', - WS: 'Samoa', - SM: 'San Marino', - ST: 'Sao Tome and Principe', - SA: 'Saudi Arabia', - SN: 'Senegal', - RS: 'Serbia', - SC: 'Seychelles', - SL: 'Sierra Leone', - SG: 'Singapore', - SX: 'Sint Maarten (Dutch part)', - SK: 'Slovakia', - SI: 'Slovenia', - SB: 'Solomon Islands', - SO: 'Somalia', - ZA: 'South Africa', - GS: 'South Georgia and the South Sandwich Islands', - SS: 'South Sudan', - ES: 'Spain', - LK: 'Sri Lanka', - SD: 'Sudan', - SR: 'Suriname', - SJ: 'Svalbard and Jan Mayen', - SZ: 'Swaziland', - SE: 'Sweden', - CH: 'Switzerland', - SY: 'Syrian Arab Republic', - TW: 'Taiwan, Province of China', - TJ: 'Tajikistan', - TZ: 'Tanzania, United Republic of', - TH: 'Thailand', - TL: 'Timor-Leste', - TG: 'Togo', - TK: 'Tokelau', - TO: 'Tonga', - TT: 'Trinidad and Tobago', - TN: 'Tunisia', - TR: 'Turkey', - TM: 'Turkmenistan', - TC: 'Turks and Caicos Islands', - TV: 'Tuvalu', - UG: 'Uganda', - UA: 'Ukraine', - AE: 'United Arab Emirates', - GB: 'United Kingdom', - US: 'United States', - UM: 'United States Minor Outlying Islands', - UY: 'Uruguay', - UZ: 'Uzbekistan', - VU: 'Vanuatu', - VE: 'Venezuela, Bolivarian Republic of', - VN: 'Viet Nam', - VG: 'Virgin Islands, British', - VI: 'Virgin Islands, U.S.', - WF: 'Wallis and Futuna', - EH: 'Western Sahara', - YE: 'Yemen', - ZM: 'Zambia', - ZW: 'Zimbabwe', -}; - -export type CountryCode = keyof typeof COUNTRIES; -export const COUNTRY_CODES = Object.keys(COUNTRIES) as CountryCode[]; +export const COUNTRY_CODES = [ + 'AF', // 'Afghanistan', + 'AX', // 'Åland Islands', + 'AL', // 'Albania', + 'DZ', // 'Algeria', + 'AS', // 'American Samoa', + 'AD', // 'Andorra', + 'AO', // 'Angola', + 'AI', // 'Anguilla', + 'AQ', // 'Antarctica', + 'AG', // 'Antigua and Barbuda', + 'AR', // 'Argentina', + 'AM', // 'Armenia', + 'AW', // 'Aruba', + 'AU', // 'Australia', + 'AT', // 'Austria', + 'AZ', // 'Azerbaijan', + 'BS', // 'Bahamas', + 'BH', // 'Bahrain', + 'BD', // 'Bangladesh', + 'BB', // 'Barbados', + 'BY', // 'Belarus', + 'BE', // 'Belgium', + 'BZ', // 'Belize', + 'BJ', // 'Benin', + 'BM', // 'Bermuda', + 'BT', // 'Bhutan', + 'BO', // 'Bolivia, Plurinational State of', + 'BQ', // 'Bonaire, Sint Eustatius and Saba', + 'BA', // 'Bosnia and Herzegovina', + 'BW', // 'Botswana', + 'BV', // 'Bouvet Island', + 'BR', // 'Brazil', + 'IO', // 'British Indian Ocean Territory', + 'BN', // 'Brunei Darussalam', + 'BG', // 'Bulgaria', + 'BF', // 'Burkina Faso', + 'BI', // 'Burundi', + 'KH', // 'Cambodia', + 'CM', // 'Cameroon', + 'CA', // 'Canada', + 'CV', // 'Cape Verde', + 'KY', // 'Cayman Islands', + 'CF', // 'Central African Republic', + 'TD', // 'Chad', + 'CL', // 'Chile', + 'CN', // 'China', + 'CX', // 'Christmas Island', + 'CC', // 'Cocos (Keeling) Islands', + 'CO', // 'Colombia', + 'KM', // 'Comoros', + 'CG', // 'Congo', + 'CD', // 'Congo, the Democratic Republic of the', + 'CK', // 'Cook Islands', + 'CR', // 'Costa Rica', + 'CI', // "Côte d'Ivoire", + 'HR', // 'Croatia', + 'CU', // 'Cuba', + 'CW', // 'Curaçao', + 'CY', // 'Cyprus', + 'CZ', // 'Czech Republic', + 'DK', // 'Denmark', + 'DJ', // 'Djibouti', + 'DM', // 'Dominica', + 'DO', // 'Dominican Republic', + 'EC', // 'Ecuador', + 'EG', // 'Egypt', + 'SV', // 'El Salvador', + 'GQ', // 'Equatorial Guinea', + 'ER', // 'Eritrea', + 'EE', // 'Estonia', + 'ET', // 'Ethiopia', + 'FK', // 'Falkland Islands (Malvinas)', + 'FO', // 'Faroe Islands', + 'FJ', // 'Fiji', + 'FI', // 'Finland', + 'FR', // 'France', + 'GF', // 'French Guiana', + 'PF', // 'French Polynesia', + 'TF', // 'French Southern Territories', + 'GA', // 'Gabon', + 'GM', // 'Gambia', + 'GE', // 'Georgia', + 'DE', // 'Germany', + 'GH', // 'Ghana', + 'GI', // 'Gibraltar', + 'GR', // 'Greece', + 'GL', // 'Greenland', + 'GD', // 'Grenada', + 'GP', // 'Guadeloupe', + 'GU', // 'Guam', + 'GT', // 'Guatemala', + 'GG', // 'Guernsey', + 'GN', // 'Guinea', + 'GW', // 'Guinea-Bissau', + 'GY', // 'Guyana', + 'HT', // 'Haiti', + 'HM', // 'Heard Island and McDonald Islands', + 'VA', // 'Holy See (Vatican City State)', + 'HN', // 'Honduras', + 'HK', // 'Hong Kong', + 'HU', // 'Hungary', + 'IS', // 'Iceland', + 'IN', // 'India', + 'ID', // 'Indonesia', + 'IR', // 'Iran, Islamic Republic of', + 'IQ', // 'Iraq', + 'IE', // 'Ireland', + 'IM', // 'Isle of Man', + 'IL', // 'Israel', + 'IT', // 'Italy', + 'JM', // 'Jamaica', + 'JP', // 'Japan', + 'JE', // 'Jersey', + 'JO', // 'Jordan', + 'KZ', // 'Kazakhstan', + 'KE', // 'Kenya', + 'KI', // 'Kiribati', + 'KP', // "Korea, Democratic People's Republic of", + 'KR', // 'Korea, Republic of', + 'KW', // 'Kuwait', + 'KG', // 'Kyrgyzstan', + 'LA', // "Lao People's Democratic Republic", + 'LV', // 'Latvia', + 'LB', // 'Lebanon', + 'LS', // 'Lesotho', + 'LR', // 'Liberia', + 'LY', // 'Libya', + 'LI', // 'Liechtenstein', + 'LT', // 'Lithuania', + 'LU', // 'Luxembourg', + 'MO', // 'Macao', + 'MK', // 'Macedonia, the Former Yugoslav Republic of', + 'MG', // 'Madagascar', + 'MW', // 'Malawi', + 'MY', // 'Malaysia', + 'MV', // 'Maldives', + 'ML', // 'Mali', + 'MT', // 'Malta', + 'MH', // 'Marshall Islands', + 'MQ', // 'Martinique', + 'MR', // 'Mauritania', + 'MU', // 'Mauritius', + 'YT', // 'Mayotte', + 'MX', // 'Mexico', + 'FM', // 'Micronesia, Federated States of', + 'MD', // 'Moldova, Republic of', + 'MC', // 'Monaco', + 'MN', // 'Mongolia', + 'ME', // 'Montenegro', + 'MS', // 'Montserrat', + 'MA', // 'Morocco', + 'MZ', // 'Mozambique', + 'MM', // 'Myanmar', + 'NA', // 'Namibia', + 'NR', // 'Nauru', + 'NP', // 'Nepal', + 'NL', // 'Netherlands', + 'NC', // 'New Caledonia', + 'NZ', // 'New Zealand', + 'NI', // 'Nicaragua', + 'NE', // 'Niger', + 'NG', // 'Nigeria', + 'NU', // 'Niue', + 'NF', // 'Norfolk Island', + 'MP', // 'Northern Mariana Islands', + 'NO', // 'Norway', + 'OM', // 'Oman', + 'PK', // 'Pakistan', + 'PW', // 'Palau', + 'PS', // 'Palestine, State of', + 'PA', // 'Panama', + 'PG', // 'Papua New Guinea', + 'PY', // 'Paraguay', + 'PE', // 'Peru', + 'PH', // 'Philippines', + 'PN', // 'Pitcairn', + 'PL', // 'Poland', + 'PT', // 'Portugal', + 'PR', // 'Puerto Rico', + 'QA', // 'Qatar', + 'RE', // 'Réunion', + 'RO', // 'Romania', + 'RU', // 'Russian Federation', + 'RW', // 'Rwanda', + 'BL', // 'Saint Barthélemy', + 'SH', // 'Saint Helena, Ascension and Tristan da Cunha', + 'KN', // 'Saint Kitts and Nevis', + 'LC', // 'Saint Lucia', + 'MF', // 'Saint Martin (French part)', + 'PM', // 'Saint Pierre and Miquelon', + 'VC', // 'Saint Vincent and the Grenadines', + 'WS', // 'Samoa', + 'SM', // 'San Marino', + 'ST', // 'Sao Tome and Principe', + 'SA', // 'Saudi Arabia', + 'SN', // 'Senegal', + 'RS', // 'Serbia', + 'SC', // 'Seychelles', + 'SL', // 'Sierra Leone', + 'SG', // 'Singapore', + 'SX', // 'Sint Maarten (Dutch part)', + 'SK', // 'Slovakia', + 'SI', // 'Slovenia', + 'SB', // 'Solomon Islands', + 'SO', // 'Somalia', + 'ZA', // 'South Africa', + 'GS', // 'South Georgia and the South Sandwich Islands', + 'SS', // 'South Sudan', + 'ES', // 'Spain', + 'LK', // 'Sri Lanka', + 'SD', // 'Sudan', + 'SR', // 'Suriname', + 'SJ', // 'Svalbard and Jan Mayen', + 'SZ', // 'Swaziland', + 'SE', // 'Sweden', + 'CH', // 'Switzerland', + 'SY', // 'Syrian Arab Republic', + 'TW', // 'Taiwan, Province of China', + 'TJ', // 'Tajikistan', + 'TZ', // 'Tanzania, United Republic of', + 'TH', // 'Thailand', + 'TL', // 'Timor-Leste', + 'TG', // 'Togo', + 'TK', // 'Tokelau', + 'TO', // 'Tonga', + 'TT', // 'Trinidad and Tobago', + 'TN', // 'Tunisia', + 'TR', // 'Turkey', + 'TM', // 'Turkmenistan', + 'TC', // 'Turks and Caicos Islands', + 'TV', // 'Tuvalu', + 'UG', // 'Uganda', + 'UA', // 'Ukraine', + 'AE', // 'United Arab Emirates', + 'GB', // 'United Kingdom', + 'US', // 'United States', + 'UM', // 'United States Minor Outlying Islands', + 'UY', // 'Uruguay', + 'UZ', // 'Uzbekistan', + 'VU', // 'Vanuatu', + 'VE', // 'Venezuela, Bolivarian Republic of', + 'VN', // 'Viet Nam', + 'VG', // 'Virgin Islands, British', + 'VI', // 'Virgin Islands, U.S.', + 'WF', // 'Wallis and Futuna', + 'EH', // 'Western Sahara', + 'YE', // 'Yemen', + 'ZM', // 'Zambia', + 'ZW', // 'Zimbabwe', +] as const; +export type CountryCode = (typeof COUNTRY_CODES)[number]; diff --git a/shared/src/types/currency.ts b/shared/src/types/currency.ts index 9a3cf2ea5..2bcf72cde 100644 --- a/shared/src/types/currency.ts +++ b/shared/src/types/currency.ts @@ -1,8 +1,10 @@ +import { CountryCode } from './country'; + export const CURRENCIES = ['CHF', 'EUR', 'USD', 'SLE'] as const; export type Currency = (typeof CURRENCIES)[number]; export const FALLBACK_CURRENCY: Currency = 'USD'; -const countryToCurrency = new Map([ +const countryToCurrency = new Map([ ['AD', 'EUR'], ['AL', 'EUR'], ['AM', 'EUR'], @@ -38,15 +40,14 @@ const countryToCurrency = new Map([ ['MT', 'EUR'], ['NL', 'EUR'], ['NO', 'EUR'], - ['PO', 'EUR'], + ['PL', 'EUR'], ['PT', 'EUR'], ]); -export const bestGuessCurrency = (country: string | undefined): Currency => { - // best guess mapping from two-letter country code to supported currency +export const bestGuessCurrency = (country: CountryCode | undefined): Currency => { + // best guess mapping from two-letter country code to a supported currency if (!country) return FALLBACK_CURRENCY; - const uppercaseCountry = country.toUpperCase(); - const currency = countryToCurrency.get(uppercaseCountry); + const currency = countryToCurrency.get(country); return currency || FALLBACK_CURRENCY; }; diff --git a/ui/src/components/checkbox.tsx b/ui/src/components/checkbox.tsx new file mode 100644 index 000000000..b80f924f8 --- /dev/null +++ b/ui/src/components/checkbox.tsx @@ -0,0 +1,27 @@ +'use client'; + +import * as CheckboxPrimitive from '@radix-ui/react-checkbox'; +import { Check } from 'lucide-react'; +import * as React from 'react'; +import { cn } from '../lib/utils'; + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)); +Checkbox.displayName = CheckboxPrimitive.Root.displayName; + +export { Checkbox }; diff --git a/ui/src/index.ts b/ui/src/index.ts index 8f1c81932..3f57d5ac1 100644 --- a/ui/src/index.ts +++ b/ui/src/index.ts @@ -6,6 +6,7 @@ export * from './components/badge'; export * from './components/button'; export * from './components/card'; export * from './components/carousel'; +export * from './components/checkbox'; export * from './components/collapsible'; export * from './components/containers'; export * from './components/dialog'; diff --git a/website/package.json b/website/package.json index 1672117c1..5cea1beab 100644 --- a/website/package.json +++ b/website/package.json @@ -20,6 +20,7 @@ "dependencies": { "@heroicons/react": "^2.0.18", "@icons-pack/react-simple-icons": "^9.1.0", + "@radix-ui/react-checkbox": "^1.0.4", "@socialincome/shared": "^1.0.0", "@socialincome/ui": "^1.0.0", "@tanstack/react-query": "^5.8.4", diff --git a/website/src/app/[lang]/[region]/(website)/(home)/section-2.tsx b/website/src/app/[lang]/[region]/(website)/(home)/section-2.tsx index 3777c59c3..ac9c37d86 100644 --- a/website/src/app/[lang]/[region]/(website)/(home)/section-2.tsx +++ b/website/src/app/[lang]/[region]/(website)/(home)/section-2.tsx @@ -48,7 +48,7 @@ export function Section2({ vimeoVideoId, translations }: Section2Props) { - + diff --git a/website/src/app/[lang]/[region]/(website)/login/login-form.tsx b/website/src/app/[lang]/[region]/(website)/login/login-form.tsx index 8b6b65060..442c10351 100644 --- a/website/src/app/[lang]/[region]/(website)/login/login-form.tsx +++ b/website/src/app/[lang]/[region]/(website)/login/login-form.tsx @@ -50,6 +50,7 @@ export default function LoginForm({ lang, region, translations }: LoginFormProps router.push(`/${lang}/${region}/me`); }) .catch((error: FirebaseError) => { + setSubmitting(false); if (error.code === 'auth/wrong-password' || error.code === 'auth/user-not-found') toast.error(translations.invalidUserOrPassword); }); diff --git a/website/src/app/[lang]/[region]/(website)/our-work/(sections)/our-work.tsx b/website/src/app/[lang]/[region]/(website)/our-work/(sections)/our-work.tsx index b01038550..20686bbcc 100644 --- a/website/src/app/[lang]/[region]/(website)/our-work/(sections)/our-work.tsx +++ b/website/src/app/[lang]/[region]/(website)/our-work/(sections)/our-work.tsx @@ -35,7 +35,7 @@ export async function OurWork({ params }: DefaultPageProps) { - + diff --git a/website/src/app/[lang]/[region]/donate/success/stripe/[session]/page.tsx b/website/src/app/[lang]/[region]/donate/success/stripe/[session]/page.tsx index a0c993a04..5e4aceb09 100644 --- a/website/src/app/[lang]/[region]/donate/success/stripe/[session]/page.tsx +++ b/website/src/app/[lang]/[region]/donate/success/stripe/[session]/page.tsx @@ -52,6 +52,7 @@ export default async function Page({ params: { lang, region, session } }: Stripe country: translator.t('success.user-form.country'), gender: translator.t('success.user-form.gender'), referral: translator.t('success.user-form.referral'), + acceptTermsAndConditions: translator.t('success.user-form.accept-terms-and-conditions'), referrals: { familyfriends: translator.t('success.user-form.referrals.familyfriends'), work: translator.t('success.user-form.referrals.work'), diff --git a/website/src/app/[lang]/[region]/donate/success/stripe/[session]/success-form.tsx b/website/src/app/[lang]/[region]/donate/success/stripe/[session]/success-form.tsx index 052796df3..7fd8850f6 100644 --- a/website/src/app/[lang]/[region]/donate/success/stripe/[session]/success-form.tsx +++ b/website/src/app/[lang]/[region]/donate/success/stripe/[session]/success-form.tsx @@ -8,6 +8,7 @@ import { COUNTRY_CODES, CountryCode } from '@socialincome/shared/src/types/count import { GENDER_OPTIONS, UserReferralSource } from '@socialincome/shared/src/types/user'; import { Button, + Checkbox, Form, FormControl, FormField, @@ -32,6 +33,7 @@ type SuccessFormProps = { region: WebsiteRegion; stripeCheckoutSessionId: string; translations: { + acceptTermsAndConditions: string; firstname: string; lastname: string; email: string; @@ -77,6 +79,7 @@ export function SuccessForm({ country: z.enum([firstCountry, ...restCountries]), gender: z.enum(GENDER_OPTIONS), referral: z.nativeEnum(UserReferralSource), + termsAndConditions: z.literal(true), }); type FormSchema = z.infer; @@ -87,6 +90,7 @@ export function SuccessForm({ firstname: firstname || '', lastname: lastname || '', country: country, + termsAndConditions: false, }, }); @@ -170,7 +174,7 @@ export function SuccessForm({ - {COUNTRY_CODES.map((country) => ( + {COUNTRY_CODES.map((country: CountryCode) => ( {countryTranslator?.t(country)} @@ -230,6 +234,20 @@ export function SuccessForm({ )} /> + ( + + + + +
+ +
+
+ )} + /> diff --git a/website/src/components/footer/footer.tsx b/website/src/components/footer/footer.tsx index 2fe5bd9ec..574a25273 100644 --- a/website/src/components/footer/footer.tsx +++ b/website/src/components/footer/footer.tsx @@ -151,7 +151,6 @@ export default async function Footer({ lang, region }: DefaultParams) { url={`/${lang}/${region}/about-us#100-percent-model`} /> -
diff --git a/website/src/components/vimeo-video.tsx b/website/src/components/vimeo-video.tsx index ad8adedec..49d0b5412 100644 --- a/website/src/components/vimeo-video.tsx +++ b/website/src/components/vimeo-video.tsx @@ -1,9 +1,14 @@ 'use client'; -import Player from '@vimeo/player'; +import Player, { Options } from '@vimeo/player'; import { useEffect, useRef } from 'react'; -export function VimeoVideo({ videoId }: { videoId: number }) { +type VimeoVideoProps = { + videoId: number; + videoOptions?: Options; +}; + +export function VimeoVideo({ videoId, videoOptions }: VimeoVideoProps) { const playerRef = useRef(null); useEffect(() => { @@ -12,9 +17,10 @@ export function VimeoVideo({ videoId }: { videoId: number }) { id: videoId, controls: true, responsive: true, + ...videoOptions, }); } - }, [videoId]); + }, [videoId, videoOptions]); return
; } diff --git a/website/src/i18n.ts b/website/src/i18n.ts index ae34776c1..efc66e287 100644 --- a/website/src/i18n.ts +++ b/website/src/i18n.ts @@ -1,6 +1,5 @@ import { LANGUAGE_COOKIE, REGION_COOKIE } from '@/app/[lang]/[region]'; import { LanguageCode } from '@socialincome/shared/src/types/language'; -import { Translator } from '@socialincome/shared/src/utils/i18n'; import langParser from 'accept-language-parser'; import { NextRequest } from 'next/server'; import { Currency } from '../../shared/src/types/currency'; @@ -18,12 +17,6 @@ export type WebsiteCurrency = Extract; export const defaultCurrency: WebsiteCurrency = 'USD'; export const websiteCurrencies: WebsiteCurrency[] = ['USD', 'EUR', 'CHF']; -export const getCurrencyTranslations = (currencies: WebsiteCurrency[], translator: Translator) => - currencies.map((currency) => ({ - code: currency, - translation: translator.t(`currencies.${currency}`), - })); - export const findBestLocale = ( request: NextRequest, ): { @@ -47,7 +40,9 @@ export const findBestLocale = ( } const options = langParser.parse(request.headers.get('Accept-Language') || 'en'); - const requestRegion = request.geo?.country; + const requestCountry = request.geo?.country; + console.info('Country set in request header:', requestCountry); + const bestOption = options.find( (option) => option.code && @@ -59,7 +54,7 @@ export const findBestLocale = ( return { language: (bestOption?.code as WebsiteLanguage) || defaultLanguage, region: - (websiteRegions.includes(requestRegion as WebsiteRegion) && (requestRegion as WebsiteRegion)) || + (websiteRegions.includes(requestCountry?.toLowerCase() as WebsiteRegion) && (requestCountry as WebsiteRegion)) || (bestOption?.region as WebsiteRegion) || defaultRegion, }; diff --git a/website/src/middleware.ts b/website/src/middleware.ts index 11e70a322..fd620c51d 100644 --- a/website/src/middleware.ts +++ b/website/src/middleware.ts @@ -1,5 +1,6 @@ import { CURRENCY_COOKIE } from '@/app/[lang]/[region]'; import { WebsiteLanguage, WebsiteRegion, allWebsiteLanguages, findBestLocale, websiteRegions } from '@/i18n'; +import { CountryCode } from '@socialincome/shared/src/types/country'; import { NextRequest, NextResponse } from 'next/server'; import { bestGuessCurrency, isValidCurrency } from '../../shared/src/types/currency'; @@ -14,8 +15,9 @@ export const currencyMiddleware = (request: NextRequest, response: NextResponse) // Checks if a valid currency is set as a cookie, and sets one with the best guess if not. if (request.cookies.has(CURRENCY_COOKIE) && isValidCurrency(request.cookies.get(CURRENCY_COOKIE)?.value)) return response; - const region = request.nextUrl.pathname.split('/').at(2); - const currency = bestGuessCurrency(region); + // We use the country code from the request header if available. If not, we use the region/country from the url path. + const requestCountry = request.geo?.country || request.nextUrl.pathname.split('/').at(2)?.toUpperCase(); + const currency = bestGuessCurrency(requestCountry as CountryCode); response.cookies.set({ name: CURRENCY_COOKIE, value: currency, path: '/', maxAge: 60 * 60 * 24 * 365 }); // 1 year return response; };