Fix club membership form in dark mode
All checks were successful
Build Production Image / Build Production Image (push) Successful in 53s
All checks were successful
Build Production Image / Build Production Image (push) Successful in 53s
This commit is contained in:
parent
7190b306e7
commit
f62e434dff
@ -2,12 +2,12 @@
|
||||
import { type Metadata } from 'next'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
import dynamic from "next/dynamic";
|
||||
import clsx from 'clsx'
|
||||
|
||||
import { Container } from '@/components/Container'
|
||||
import { UserPlusIcon, GiftIcon, EnvelopeIcon, UserGroupIcon } from '@heroicons/react/24/solid'
|
||||
import interiorEmptyImage from '@/images/photos/interior-empty.jpg'
|
||||
import { ClubPayment } from './payment';
|
||||
|
||||
function SocialLink({
|
||||
className,
|
||||
@ -43,6 +43,15 @@ export const metadata: Metadata = {
|
||||
// TODO: Replace interiorEmptyImage with a photo from a potluck
|
||||
|
||||
export default function Club() {
|
||||
|
||||
// Dynamic import since ClubPayment uses `document`
|
||||
const ClubPayment = dynamic(
|
||||
() => {
|
||||
return import("./payment");
|
||||
},
|
||||
{ ssr: false }
|
||||
);
|
||||
|
||||
return (
|
||||
<Container className="mt-16 sm:mt-32">
|
||||
<div className="grid grid-cols-1 gap-y-16 lg:grid-cols-2 lg:grid-rows-[auto_1fr] lg:gap-y-12">
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import React, { useEffect, useState, FormEvent } from 'react';
|
||||
import React, { useEffect, useState, FormEvent, useCallback } from 'react';
|
||||
import { AddressElement, Elements } from '@stripe/react-stripe-js';
|
||||
import { Appearance, StripeAddressElementOptions, StripeElementsOptions, loadStripe } from '@stripe/stripe-js';
|
||||
import {
|
||||
@ -166,7 +166,7 @@ function CheckoutForm({
|
||||
|
||||
{/* Membership Type */}
|
||||
<RadioGroup value={selectedMembershipLevel} onChange={setSelectedMembershipLevel} className="space-y-3">
|
||||
<RadioGroup.Label className="text-base font-semibold leading-6 text-gray-900">
|
||||
<RadioGroup.Label className="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Select a membership type
|
||||
</RadioGroup.Label>
|
||||
|
||||
@ -177,8 +177,8 @@ function CheckoutForm({
|
||||
value={membership}
|
||||
className={({ active }) =>
|
||||
classNames(
|
||||
active ? 'border-indigo-600 ring-2 ring-indigo-600' : 'border-gray-300',
|
||||
'relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none'
|
||||
active ? 'border-indigo-600 ring-2 ring-indigo-600' : 'border-gray-200 dark:border-gray-500',
|
||||
'relative flex cursor-pointer rounded-lg border bg-white hover:bg-gray-50 hover:dark:bg-zinc-600 dark:bg-zinc-700 p-4 shadow-sm focus:outline-none'
|
||||
)
|
||||
}
|
||||
>
|
||||
@ -186,7 +186,7 @@ function CheckoutForm({
|
||||
<>
|
||||
<span className="flex flex-1 items-center justify-between ">
|
||||
<span className="flex flex-col">
|
||||
<RadioGroup.Label as="span" className="block text-sm font-medium text-gray-900">
|
||||
<RadioGroup.Label as="span" className="block text-sm font-medium text-gray-900 dark:text-white">
|
||||
{membership.title}
|
||||
</RadioGroup.Label>
|
||||
<RadioGroup.Description as="span" className="mt-1 flex items-center text-sm text-gray-500">
|
||||
@ -194,7 +194,7 @@ function CheckoutForm({
|
||||
</RadioGroup.Description>
|
||||
</span>
|
||||
<RadioGroup.Description as="span" className="ml-8 text-sm font-medium">
|
||||
<span className="text-gray-900">${membership.price}</span>
|
||||
<span className="text-gray-900 dark:text-white">${membership.price}</span>
|
||||
<span className="text-gray-500">/yr</span>
|
||||
</RadioGroup.Description>
|
||||
</span>
|
||||
@ -215,7 +215,7 @@ function CheckoutForm({
|
||||
|
||||
{/* Additional donation */}
|
||||
<RadioGroup value={selectedAdditionalDonation} onChange={setSelectedAdditionalDonation} className="space-y-3">
|
||||
<RadioGroup.Label className="text-base font-semibold leading-6 text-gray-900">
|
||||
<RadioGroup.Label className="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Additional donation
|
||||
</RadioGroup.Label>
|
||||
<div className="grid grid-cols-3 gap-3 sm:grid-cols-5">
|
||||
@ -228,9 +228,9 @@ function CheckoutForm({
|
||||
'cursor-pointer focus:outline-none',
|
||||
option === -1 ? 'col-span-2' : '',
|
||||
checked
|
||||
? 'ring-2 ring-indigo-600 ring-offset-2'
|
||||
: 'ring-1 ring-inset ring-gray-300 bg-white text-gray-900 hover:bg-gray-50',
|
||||
'flex items-center justify-center rounded-md py-3 px-3 text-sm font-semibold sm:flex-1'
|
||||
? 'ring-2 ring-indigo-600'
|
||||
: 'ring-1 ring-inset ring-gray-200 dark:ring-gray-500 text-gray-900 dark:text-white hover:bg-gray-50 hover:dark:bg-zinc-600',
|
||||
'flex items-center justify-center rounded-md py-3 px-3 text-sm font-semibold sm:flex-1 bg-white dark:bg-zinc-700'
|
||||
)
|
||||
}
|
||||
>
|
||||
@ -250,7 +250,7 @@ function CheckoutForm({
|
||||
min="0"
|
||||
step="1"
|
||||
onChange={(e) => setCustomAmount(e.target.value)}
|
||||
className="block w-full rounded-md border-0 py-1.5 pl-7 pr-12 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-gray-500 sm:text-sm sm:leading-6"
|
||||
className="block w-full rounded-md border-0 py-1.5 pl-7 pr-12 text-gray-900 dark:text-white dark:bg-zinc-700 ring-1 ring-inset ring-gray-200 dark:ring-gray-500 placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-gray-500 sm:text-sm sm:leading-6"
|
||||
placeholder="Custom"
|
||||
aria-describedby="price-currency"
|
||||
/>
|
||||
@ -274,12 +274,12 @@ function CheckoutForm({
|
||||
</RadioGroup>
|
||||
|
||||
<div className="space-y-3">
|
||||
<h2 className="text-base font-semibold leading-6 text-gray-900">
|
||||
<h2 className="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
About you
|
||||
</h2>
|
||||
|
||||
<div className="rounded-md mb-3 px-3 pb-1.5 pt-2.5 shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-indigo-600">
|
||||
<label htmlFor="name" className="block text-xs font-medium text-gray-900">
|
||||
<div className="rounded-md mb-3 px-3 pb-1.5 pt-2.5 shadow-sm ring-1 ring-inset ring-gray-200 dark:ring-gray-500 focus-within:ring-2 focus-within:ring-indigo-600 dark:bg-zinc-700 dark:text-white">
|
||||
<label htmlFor="name" className="block text-xs font-medium text-gray-900 dark:text-zinc-400">
|
||||
Email
|
||||
</label>
|
||||
<input
|
||||
@ -288,7 +288,7 @@ function CheckoutForm({
|
||||
id="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
className="block w-full border-0 p-0 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
|
||||
className="block w-full border-0 p-0 dark:bg-zinc-700 text-gray-900 dark:text-white placeholder:text-gray-400 focus:ring-0 sm:text-sm sm:leading-6"
|
||||
placeholder="you@example.com"
|
||||
/>
|
||||
</div>
|
||||
@ -296,7 +296,7 @@ function CheckoutForm({
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<h2 className="text-base font-semibold leading-6 text-gray-900">
|
||||
<h2 className="text-base font-semibold leading-6 text-gray-900 dark:text-white">
|
||||
Payment
|
||||
</h2>
|
||||
<div className="mt-1 text-sm text-gray-500">
|
||||
@ -329,9 +329,37 @@ function CheckoutForm({
|
||||
);
|
||||
}
|
||||
|
||||
export function ClubPayment() {
|
||||
const DEFAULT_OPTIONS = {
|
||||
config: { attributes: true, childList: true, subtree: true },
|
||||
};
|
||||
|
||||
function useMutationObservable(targetEl: Node, cb: MutationCallback, options = DEFAULT_OPTIONS) {
|
||||
const [observer, setObserver] = useState<MutationObserver | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const obs = new MutationObserver(cb);
|
||||
setObserver(obs);
|
||||
}, [cb, options, setObserver]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!observer) return;
|
||||
const { config } = options;
|
||||
observer.observe(targetEl, config);
|
||||
return () => {
|
||||
if (observer) {
|
||||
observer.disconnect();
|
||||
}
|
||||
};
|
||||
}, [observer, targetEl, options]);
|
||||
}
|
||||
|
||||
export default function ClubPayment() {
|
||||
const [clientSecret, setClientSecret] = useState('');
|
||||
const [paymentIntent, setPaymentIntent] = useState('');
|
||||
|
||||
const htmlEl = document.getElementsByTagName('html')[0];
|
||||
const darkTheme = htmlEl.classList.contains("dark");
|
||||
|
||||
useEffect(() => {
|
||||
// Create PaymentIntent as soon as the page loads using our local API
|
||||
fetch('api/stripe_intent', {
|
||||
@ -349,15 +377,36 @@ export function ClubPayment() {
|
||||
});
|
||||
}, []);
|
||||
|
||||
const styles = getComputedStyle(htmlEl);
|
||||
|
||||
const appearance: Appearance = {
|
||||
theme: 'stripe',
|
||||
variables: {
|
||||
colorBackground: styles.getPropertyValue('--stripe-background'),
|
||||
colorText: styles.getPropertyValue('--stripe-foreground'),
|
||||
},
|
||||
labels: 'floating',
|
||||
};
|
||||
|
||||
const cb = useCallback(
|
||||
() => {
|
||||
const updatedHtmlEl = document.getElementsByTagName('html')[0];
|
||||
const updatedDarkTheme = updatedHtmlEl.classList.contains("dark");
|
||||
|
||||
if (updatedDarkTheme !== darkTheme) {
|
||||
location.reload();
|
||||
}
|
||||
},
|
||||
[darkTheme]
|
||||
)
|
||||
|
||||
useMutationObservable(htmlEl, cb);
|
||||
|
||||
const options: StripeElementsOptions = {
|
||||
clientSecret,
|
||||
appearance
|
||||
appearance,
|
||||
}
|
||||
|
||||
return <>
|
||||
{clientSecret && (
|
||||
<Elements options={options}
|
||||
|
@ -2,3 +2,15 @@
|
||||
@import 'tailwindcss/components';
|
||||
@import './prism.css';
|
||||
@import 'tailwindcss/utilities';
|
||||
|
||||
:root {
|
||||
/* Your default theme */
|
||||
|
||||
--stripe-background: #FFFFFF;
|
||||
--stripe-foreground: #000000;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--stripe-background: #3f3f46;
|
||||
--stripe-foreground: #E4E4E7;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user