Changing to supercast.
parent
f80d7efb9d
commit
ce5f902493
@ -1,27 +0,0 @@
|
|||||||
import Link from 'next/link';
|
|
||||||
import { redirect } from 'next/navigation';
|
|
||||||
|
|
||||||
import { cookies } from 'next/headers';
|
|
||||||
|
|
||||||
import db from '@/db';
|
|
||||||
|
|
||||||
async function getSession() {
|
|
||||||
const cookieStore = cookies();
|
|
||||||
const sessionId = cookieStore.get('session');
|
|
||||||
if (!sessionId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const { user_id: userId } = await db.get('select user_id from sessions where session_id=?;', sessionId.value);
|
|
||||||
if (!userId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return userId;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function Layout({ children }) {
|
|
||||||
const userId = await getSession();
|
|
||||||
if (!userId) {
|
|
||||||
redirect('/reactors');
|
|
||||||
}
|
|
||||||
return children;
|
|
||||||
};
|
|
@ -1,52 +0,0 @@
|
|||||||
import { cookies } from 'next/headers';
|
|
||||||
|
|
||||||
import db from '@/db';
|
|
||||||
import { accountFeedURL } from '@/paths';
|
|
||||||
|
|
||||||
import { Container } from '@/components/Container';
|
|
||||||
|
|
||||||
async function getSession() {
|
|
||||||
const cookieStore = cookies();
|
|
||||||
const sessionId = cookieStore.get('session');
|
|
||||||
if (!sessionId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const dbRes = await db.get('select user_id from sessions where session_id=?;', sessionId.value);
|
|
||||||
const { user_id: userId } = dbRes ? dbRes : { user_id: false };
|
|
||||||
if (!userId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return userId;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function Page() {
|
|
||||||
const userId = await getSession();
|
|
||||||
const { uuid } = await db.get('select uuid from subscriptions where user_id=?', userId);
|
|
||||||
return (
|
|
||||||
<div className="pt-16 pb-12 sm:pb-4 lg:pt-12">
|
|
||||||
<Container>
|
|
||||||
<h1 className="text-2xl font-bold leading-7 text-slate-900">
|
|
||||||
The Reactors
|
|
||||||
</h1>
|
|
||||||
<p>Thank you so much for your support! It makes this show possible!</p>
|
|
||||||
<div className="overflow-hidden rounded-lg bg-white shadow">
|
|
||||||
<div className="border-b border-gray-200 bg-white px-4 py-5 sm:px-6">
|
|
||||||
<h3 className="text-base font-semibold leading-6 text-gray-900">Your Personal Podcast Feed</h3>
|
|
||||||
</div>
|
|
||||||
<div className="px-4 py-5 sm:p-6">
|
|
||||||
<dl className="space-y-10">
|
|
||||||
<div>
|
|
||||||
<dt className="text-base font-semibold leading-7 text-gray-900">Copy/Paste URL into your podcast app:</dt>
|
|
||||||
<dd className="mt-2 text-base leading-7 text-gray-600"><a href={accountFeedURL(uuid)}>{accountFeedURL(uuid)}</a></dd>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<dt className="text-base font-semibold leading-7 text-gray-900">Instructions For Common Podcast Apps:</dt>
|
|
||||||
<dd className="mt-2 text-base leading-7 text-gray-600"><a href="/todo">Here</a></dd>
|
|
||||||
</div>
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,143 +0,0 @@
|
|||||||
export const dynamic = 'force-dynamic';
|
|
||||||
|
|
||||||
import Link from 'next/link'
|
|
||||||
import Stripe from 'stripe';
|
|
||||||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
|
||||||
|
|
||||||
import { XCircleIcon } from '@heroicons/react/20/solid'
|
|
||||||
|
|
||||||
import { Container } from '@/components/Container';
|
|
||||||
|
|
||||||
|
|
||||||
// /reactors/create-account?csi=cs_test_a1pBB0FI8GUKnWYlCVn0RKUYXV8FRroacXjI5WVhWPlFJilm46lZwdjgac
|
|
||||||
export default async function Page({ searchParams }) {
|
|
||||||
const unexpectedError = searchParams['unexpected_error'];
|
|
||||||
const msg = searchParams['msg'];
|
|
||||||
const csi = searchParams['csi'];
|
|
||||||
const patreonMagicKey = searchParams['patreon_magic_key'];
|
|
||||||
const session = csi && await stripe.checkout.sessions.retrieve(csi);
|
|
||||||
const email = (csi && session && session.customer_details.email) || searchParams['email'];
|
|
||||||
if (unexpectedError) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
Unexpected Error sorry about that! Please contact us via <Link href="/contact">Contact</Link> and we will get it figured out!
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className="pt-16 pb-12 sm:pb-4 lg:pt-12">
|
|
||||||
<Container>
|
|
||||||
<h1 className="text-2xl font-bold leading-7 text-slate-900">
|
|
||||||
The Reactors - Create Account
|
|
||||||
</h1>
|
|
||||||
<div className="divide-y divide-slate-100 sm:mt-4 lg:mt-8 lg:border-t lg:border-slate-100">
|
|
||||||
<p>
|
|
||||||
Thank you so much for signing up to become a Reactor! We just need a password now to create an account for you!
|
|
||||||
</p>
|
|
||||||
{msg && (
|
|
||||||
<div className="rounded-md bg-red-50 p-4 mt-8">
|
|
||||||
<div className="flex">
|
|
||||||
<div className="flex-shrink-0">
|
|
||||||
<XCircleIcon className="h-5 w-5 text-red-400" aria-hidden="true" />
|
|
||||||
</div>
|
|
||||||
<div className="ml-3">
|
|
||||||
<h3 className="text-sm font-medium text-red-800">There was an error with your submission</h3>
|
|
||||||
<div className="mt-2 text-sm text-red-700">
|
|
||||||
{msg}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<form className="space-y-8" method="POST" action="/api/create-account">
|
|
||||||
<input
|
|
||||||
name="csi"
|
|
||||||
value={csi}
|
|
||||||
type="hidden"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
name="patreon_magic_key"
|
|
||||||
value={patreonMagicKey}
|
|
||||||
type="hidden"
|
|
||||||
/>
|
|
||||||
<div className="space-y-8">
|
|
||||||
<div className="pt-8">
|
|
||||||
<div className="mt-6 grid grid-cols-1 gap-y-6 gap-x-4 sm:grid-cols-6">
|
|
||||||
<div className="sm:col-span-3">
|
|
||||||
<label htmlFor="emailprefilled" className="block text-sm font-medium text-gray-700">
|
|
||||||
Email address
|
|
||||||
</label>
|
|
||||||
<div className="mt-1">
|
|
||||||
<input
|
|
||||||
id="emailprefilled"
|
|
||||||
name="emailprefilled"
|
|
||||||
type="email"
|
|
||||||
defaultValue={email}
|
|
||||||
disabled
|
|
||||||
title="Email Address (required)"
|
|
||||||
className="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
name="email"
|
|
||||||
value={email}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-6 grid grid-cols-1 gap-y-6 gap-x-4 sm:grid-cols-6">
|
|
||||||
<div className="sm:col-span-3">
|
|
||||||
<label htmlFor="password" className="block text-sm font-medium text-gray-700">
|
|
||||||
Password
|
|
||||||
</label>
|
|
||||||
<div className="mt-1">
|
|
||||||
<input
|
|
||||||
id="password"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
required
|
|
||||||
minlength="12"
|
|
||||||
title="Password (required)"
|
|
||||||
className="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="sm:col-span-3">
|
|
||||||
<label htmlFor="passwordagain" className="block text-sm font-medium text-gray-700">
|
|
||||||
Password (again)
|
|
||||||
</label>
|
|
||||||
<div className="mt-1">
|
|
||||||
<input
|
|
||||||
id="passwordagain"
|
|
||||||
name="passwordagain"
|
|
||||||
type="password"
|
|
||||||
required
|
|
||||||
minlength="12"
|
|
||||||
title="Password (required)"
|
|
||||||
className="block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="pt-5">
|
|
||||||
<div className="flex justify-end">
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="ml-3 inline-flex justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
|
||||||
>
|
|
||||||
Create Account
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,14 +0,0 @@
|
|||||||
import { Container } from '@/components/Container';
|
|
||||||
|
|
||||||
export default async function Page() {
|
|
||||||
return (
|
|
||||||
<div className="pt-16 pb-12 sm:pb-4 lg:pt-12">
|
|
||||||
<Container>
|
|
||||||
<h1 className="text-2xl font-bold leading-7 text-slate-900">
|
|
||||||
The Reactors
|
|
||||||
</h1>
|
|
||||||
<a href="https://buy.stripe.com/test_3cs01j768d65gso289">Level I</a>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,132 +0,0 @@
|
|||||||
export const dynamic = 'force-dynamic';
|
|
||||||
|
|
||||||
import Link from 'next/link'
|
|
||||||
import Stripe from 'stripe';
|
|
||||||
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
|
||||||
|
|
||||||
import { XCircleIcon } from '@heroicons/react/20/solid'
|
|
||||||
|
|
||||||
import { Container } from '@/components/Container';
|
|
||||||
|
|
||||||
|
|
||||||
// /reactors/create-account?csi=cs_test_a1pBB0FI8GUKnWYlCVn0RKUYXV8FRroacXjI5WVhWPlFJilm46lZwdjgac
|
|
||||||
export default async function Page({ searchParams }) {
|
|
||||||
const unexpectedError = searchParams['unexpected_error'];
|
|
||||||
const msg = searchParams['msg'];
|
|
||||||
const csi = searchParams['csi'];
|
|
||||||
const session = csi && await stripe.checkout.sessions.retrieve(csi);
|
|
||||||
const email = (csi && session && session.customer_details.email) || searchParams['email'];
|
|
||||||
if (unexpectedError) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
Unexpected Error sorry about that! Please contact us via <Link href="/contact">Contact</Link> and we will get it figured out!
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className="pt-16 pb-12 sm:pb-4 lg:pt-12">
|
|
||||||
<Container>
|
|
||||||
<h1 className="text-2xl font-bold leading-7 text-slate-900">
|
|
||||||
The Reactors - Sign In
|
|
||||||
</h1>
|
|
||||||
<div className="divide-y divide-slate-100 sm:mt-4 lg:mt-8 lg:border-t lg:border-slate-100">
|
|
||||||
{msg && (
|
|
||||||
<div className="rounded-md bg-red-50 p-4 mt-8">
|
|
||||||
<div className="flex">
|
|
||||||
<div className="flex-shrink-0">
|
|
||||||
<XCircleIcon className="h-5 w-5 text-red-400" aria-hidden="true" />
|
|
||||||
</div>
|
|
||||||
<div className="ml-3">
|
|
||||||
<h3 className="text-sm font-medium text-red-800">There was an error with your submission</h3>
|
|
||||||
<div className="mt-2 text-sm text-red-700" data-cy="error-message">
|
|
||||||
{msg}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
|
|
||||||
<div className="sm:mx-auto sm:w-full sm:max-w-md">
|
|
||||||
<h2 className="mt-6 text-center text-3xl font-bold tracking-tight text-gray-900">Sign in to your account</h2>
|
|
||||||
<p className="mt-2 text-center text-sm text-gray-600">
|
|
||||||
Or{' '}
|
|
||||||
<Link href='/reactors' className="font-medium text-indigo-600 hover:text-indigo-500">
|
|
||||||
sign up to become a Reactor!
|
|
||||||
</Link>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
|
|
||||||
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10 bg-gray-50">
|
|
||||||
<form className="space-y-6" method="POST" action="/api/sign-in">
|
|
||||||
<div>
|
|
||||||
<label htmlFor="email" className="block text-sm font-medium text-gray-700">
|
|
||||||
Email address
|
|
||||||
</label>
|
|
||||||
<div className="mt-1">
|
|
||||||
<input
|
|
||||||
id="email"
|
|
||||||
name="email"
|
|
||||||
type="email"
|
|
||||||
autoComplete="email"
|
|
||||||
defaultValue={email}
|
|
||||||
required
|
|
||||||
className="block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<label htmlFor="password" className="block text-sm font-medium text-gray-700">
|
|
||||||
Password
|
|
||||||
</label>
|
|
||||||
<div className="mt-1">
|
|
||||||
<input
|
|
||||||
id="password"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
autoComplete="current-password"
|
|
||||||
required
|
|
||||||
className="block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-indigo-500 sm:text-sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<div className="flex items-center">
|
|
||||||
<input
|
|
||||||
id="remember_me"
|
|
||||||
name="remember_me"
|
|
||||||
type="checkbox"
|
|
||||||
className="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500"
|
|
||||||
defaultValue="checked"
|
|
||||||
/>
|
|
||||||
<label htmlFor="remember_me" className="ml-2 block text-sm text-gray-900">
|
|
||||||
Remember me
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="text-sm">
|
|
||||||
<a href="#" className="font-medium text-indigo-600 hover:text-indigo-500">
|
|
||||||
Forgot your password?
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
className="flex w-full justify-center rounded-md border border-transparent bg-indigo-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
|
|
||||||
>
|
|
||||||
Sign in
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,72 +0,0 @@
|
|||||||
import Link from 'next/link';
|
|
||||||
import { BookOpenIcon, BanknotesIcon } from '@heroicons/react/24/outline'
|
|
||||||
|
|
||||||
import { Container } from '@/components/Container';
|
|
||||||
|
|
||||||
const features = [
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'Buy My Book!',
|
|
||||||
link: '/book',
|
|
||||||
description:
|
|
||||||
'If you want to learn more in-depth how React work then this is definitely the best way to support the show!',
|
|
||||||
icon: BookOpenIcon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Tip!',
|
|
||||||
link: 'https://buy.stripe.com/cN25nl5x2fZO4M0cMN',
|
|
||||||
description:
|
|
||||||
'Another great way to directly support the show is to send us a one-time tip! Thank you so much!',
|
|
||||||
icon: BanknotesIcon,
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
export const metadata = {
|
|
||||||
title: 'Support the Show!',
|
|
||||||
description: 'Show your support for the show with these options!'
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function Page() {
|
|
||||||
return (
|
|
||||||
<div className="pt-16 pb-12 sm:pb-4 lg:pt-12">
|
|
||||||
<Container>
|
|
||||||
<h1 className="text-2xl font-bold leading-7 text-slate-900">
|
|
||||||
Support
|
|
||||||
</h1>
|
|
||||||
</Container>
|
|
||||||
<div className="divide-y divide-slate-100 sm:mt-4 lg:mt-8 lg:border-t lg:border-slate-100">
|
|
||||||
<div className="bg-white py-24 sm:py-32">
|
|
||||||
<div className="mx-auto max-w-7xl px-6 lg:px-8">
|
|
||||||
<div className="mx-auto max-w-2xl lg:text-center">
|
|
||||||
<h2 className="text-lg font-semibold leading-8 tracking-tight text-indigo-600">Support the Show!</h2>
|
|
||||||
<p className="mt-2 text-3xl font-bold tracking-tight text-gray-900 sm:text-4xl">
|
|
||||||
Like <i>The React Show</i>? These are the best ways to support us!
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="mx-auto mt-16 max-w-2xl sm:mt-20 lg:mt-24 lg:max-w-4xl">
|
|
||||||
<dl className="grid max-w-xl grid-cols-1 gap-y-10 gap-x-8 lg:max-w-none lg:grid-cols-2 lg:gap-y-16">
|
|
||||||
{features.map((feature) => (
|
|
||||||
<div key={feature.name} className="relative pl-16">
|
|
||||||
<dt className="text-base font-semibold leading-7 text-gray-900">
|
|
||||||
<div className="absolute top-0 left-0 flex h-10 w-10 items-center justify-center rounded-lg bg-indigo-600">
|
|
||||||
<Link href={feature.link}><feature.icon className="h-6 w-6 text-white" aria-hidden="true" /></Link>
|
|
||||||
</div>
|
|
||||||
<Link
|
|
||||||
href={feature.link}
|
|
||||||
className="underline font-bold leading-6 text-pink-500 hover:text-pink-700 active:text-pink-900"
|
|
||||||
>
|
|
||||||
{feature.name}
|
|
||||||
</Link>
|
|
||||||
</dt>
|
|
||||||
<dd className="mt-2 text-base leading-7 text-gray-600">{feature.description}</dd>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
'use server';
|
|
||||||
|
|
||||||
import Link from 'next/link';
|
|
||||||
|
|
||||||
import UserMenuClient from '@/components/UserMenuClient';
|
|
||||||
|
|
||||||
import { cookies } from 'next/headers';
|
|
||||||
|
|
||||||
import db from '@/db';
|
|
||||||
|
|
||||||
async function getSession() {
|
|
||||||
const cookieStore = cookies();
|
|
||||||
const sessionId = cookieStore.get('session');
|
|
||||||
if (!sessionId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const { user_id: userId } = await db.get('select user_id from sessions where session_id=?;', sessionId.value);
|
|
||||||
if (!userId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return userId;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function ReactorsLink() {
|
|
||||||
const userId = await getSession();
|
|
||||||
if (userId) {
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
href="/reactors/account"
|
|
||||||
className="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-base font-medium"
|
|
||||||
>
|
|
||||||
Reactors
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
href="/reactors"
|
|
||||||
className="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-base font-medium"
|
|
||||||
>
|
|
||||||
Reactors
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,70 +0,0 @@
|
|||||||
'use server';
|
|
||||||
|
|
||||||
import Link from 'next/link';
|
|
||||||
|
|
||||||
import UserMenuClient from '@/components/UserMenuClient';
|
|
||||||
|
|
||||||
import { cookies } from 'next/headers';
|
|
||||||
|
|
||||||
import db from '@/db';
|
|
||||||
|
|
||||||
const signedInNavigation = [
|
|
||||||
{ name: 'Account', href: '/reactors/account' },
|
|
||||||
{ name: 'Sign Out', href: '/' },
|
|
||||||
]
|
|
||||||
|
|
||||||
async function getSession() {
|
|
||||||
const cookieStore = cookies();
|
|
||||||
const sessionId = cookieStore.get('session');
|
|
||||||
if (!sessionId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const { user_id: userId } = await db.get('select user_id from sessions where session_id=?;', sessionId.value);
|
|
||||||
if (!userId) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return userId;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default async function UserMenu() {
|
|
||||||
const userId = await getSession();
|
|
||||||
return (
|
|
||||||
<UserMenuClient>
|
|
||||||
{userId ? (
|
|
||||||
<>
|
|
||||||
<Link
|
|
||||||
href="/reactors/account"
|
|
||||||
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 active:bg-gray-100"
|
|
||||||
>
|
|
||||||
Account
|
|
||||||
</Link>
|
|
||||||
<form
|
|
||||||
method="POST"
|
|
||||||
action="/api/sign-out"
|
|
||||||
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 active:bg-gray-100"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
type="submit">
|
|
||||||
Sign Out
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Link
|
|
||||||
href="/reactors/sign-in"
|
|
||||||
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 active:bg-gray-100"
|
|
||||||
>
|
|
||||||
Sign In
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
href="/reactors"
|
|
||||||
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 active:bg-gray-100"
|
|
||||||
>
|
|
||||||
Create Account
|
|
||||||
</Link>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</UserMenuClient>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,72 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import { Fragment } from 'react'
|
|
||||||
import { Disclosure, Menu, Transition } from '@headlessui/react'
|
|
||||||
import { Bars3Icon, UserCircleIcon, XMarkIcon } from '@heroicons/react/24/outline'
|
|
||||||
|
|
||||||
function classNames(...classes) {
|
|
||||||
return classes.filter(Boolean).join(' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function UserMenu({ children }) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div>
|
|
||||||
<Menu.Button className="flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
|
|
||||||
<span className="sr-only">Open user menu</span>
|
|
||||||
<UserCircleIcon
|
|
||||||
className="h-8 w-8 rounded-full text-white"
|
|
||||||
/>
|
|
||||||
</Menu.Button>
|
|
||||||
</div>
|
|
||||||
<Transition
|
|
||||||
as={Fragment}
|
|
||||||
enter="transition ease-out duration-100"
|
|
||||||
enterFrom="transform opacity-0 scale-95"
|
|
||||||
enterTo="transform opacity-100 scale-100"
|
|
||||||
leave="transition ease-in duration-75"
|
|
||||||
leaveFrom="transform opacity-100 scale-100"
|
|
||||||
leaveTo="transform opacity-0 scale-95"
|
|
||||||
>
|
|
||||||
<Menu.Items className="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
|
|
||||||
{children.map((link, i) => (
|
|
||||||
<Menu.Item key={i}>
|
|
||||||
{link}
|
|
||||||
</Menu.Item>
|
|
||||||
))}
|
|
||||||
</Menu.Items>
|
|
||||||
</Transition>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* <Menu.Item>
|
|
||||||
* {({ active }) => (
|
|
||||||
* <a
|
|
||||||
* href="#"
|
|
||||||
* className={classNames(active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700')}
|
|
||||||
* >
|
|
||||||
* Your Profile
|
|
||||||
* </a>
|
|
||||||
* )}
|
|
||||||
* </Menu.Item>
|
|
||||||
* <Menu.Item>
|
|
||||||
* {({ active }) => (
|
|
||||||
* <a
|
|
||||||
* href="#"
|
|
||||||
* className={classNames(active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700')}
|
|
||||||
* >
|
|
||||||
* Settings
|
|
||||||
* </a>
|
|
||||||
* )}
|
|
||||||
* </Menu.Item>
|
|
||||||
* <Menu.Item>
|
|
||||||
* {({ active }) => (
|
|
||||||
* <a
|
|
||||||
* href="#"
|
|
||||||
* className={classNames(active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700')}
|
|
||||||
* >
|
|
||||||
* Sign out
|
|
||||||
* </a>
|
|
||||||
* )}
|
|
||||||
* </Menu.Item> */
|
|
Binary file not shown.
Before Width: | Height: | Size: 27 MiB |
Binary file not shown.
Before Width: | Height: | Size: 185 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.0 MiB |
Binary file not shown.
Before Width: | Height: | Size: 582 KiB |
Loading…
Reference in New Issue