242 lines
10 KiB
TypeScript
242 lines
10 KiB
TypeScript
'use client';
|
|
|
|
import 'react-loading-skeleton/dist/skeleton.css';
|
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
import { faSpinner, faCheckCircle, faXmarkCircle } from "@fortawesome/free-solid-svg-icons";
|
|
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
// import { updateIsUsernamePublic } from "./hooks/updateProfile";
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import ProtectedRoute from "../components/protected-route";
|
|
import VibrateTest from "../components/vibrate-test";
|
|
import { useSession } from "next-auth/react"
|
|
import { LoginButton, LogoutButton } from "../components/auth-buttons";
|
|
import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
|
|
import Link from 'next/link';
|
|
import { useEffect } from 'react';
|
|
import { useState } from 'react';
|
|
import { fetchPatreonCurrentlyEntitledTiers } from './hooks/patreonCurrentlyEntitledTiers';
|
|
import { Spinner } from '../components/spinner';
|
|
import { signIn, signOut } from "next-auth/react";
|
|
|
|
export default function Page() {
|
|
|
|
const queryClient = useQueryClient()
|
|
// const sessionContext = Session.useSessionContext()
|
|
// if (sessionContext.loading) {
|
|
// return <Spinner></Spinner>
|
|
// }
|
|
const { data, status, update } = useSession()
|
|
|
|
|
|
async function renewJwt() {
|
|
await signOut({ redirect: false });
|
|
await signIn("keycloak", { redirect: false });
|
|
}
|
|
|
|
// const { data: patreonTier, isPending, refetch } = useQuery({
|
|
// queryKey: ['user/tier'],
|
|
// queryFn: () => fetchPatreonCurrentlyEntitledTiers(),
|
|
// })
|
|
|
|
// const keycloakGroupQuery = useQuery({
|
|
// queryKey: ['user/group'],
|
|
// queryFn: () => fetchKeycloakGroup()
|
|
// })
|
|
|
|
// const attributesMutation = useMutation({
|
|
// mutationFn: updateIsUsernamePublic,
|
|
// mutationKey: ['user/attributes'],
|
|
// onSuccess: () => queryClient.invalidateQueries({ queryKey: ['user/attributes'] })
|
|
// })
|
|
|
|
// const metadataQuery = useQuery({
|
|
// queryKey: ['user/metadata'],
|
|
// queryFn: () => fetchMetadata()
|
|
// })
|
|
|
|
// const [ isUsernamePublic, setIsUsernamePublic ] = useState<boolean>()
|
|
// const [ username, setUsername ] = useState('')
|
|
// useEffect(() => {
|
|
// if (metadataQuery.data?.metadata) {
|
|
// setUsername(formatPatronUsername(metadataQuery.data.metadata.first_name, metadataQuery.data.metadata.last_name))
|
|
// setIsUsernamePublic(metadataQuery.data.metadata.isUsernamePublic)
|
|
// }
|
|
// }, [metadataQuery.data])
|
|
|
|
const isUsernamePublic = (data?.profile?.username_visibility === 'public')
|
|
const [isGo, setIsGo] = useState<boolean>()
|
|
|
|
// useEffect(() => {
|
|
// const fetchData = async () => {
|
|
// const res = await fetch(`${process.env.KEYCLOAK_URL}/protocol/openid-connect/token`, {
|
|
// method: 'POST',
|
|
// headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
// body: new URLSearchParams({
|
|
// client_id: process.env.KEYCLOAK_CLIENT_ID,
|
|
// client_secret: process.env.KEYCLOAK_CLIENT_SECRET,
|
|
// grant_type: 'refresh_token',
|
|
// refresh_token: session.refreshToken,
|
|
// }),
|
|
// });
|
|
|
|
// const data = await res.json();
|
|
|
|
// if (res.ok) {
|
|
// // Update session with new token
|
|
// session.accessToken = data.access_token;
|
|
// session.refreshToken = data.refresh_token;
|
|
// res.status(200).json(session);
|
|
// } else {
|
|
// res.status(400).json({ error: 'Token refresh failed' });
|
|
// }
|
|
// }
|
|
|
|
// fetchData();
|
|
// }, [isGo]);
|
|
|
|
|
|
return (
|
|
<div className="content">
|
|
{/* {(metadataQuery.isPending) && <Spinner></Spinner>} */}
|
|
<div className="section">
|
|
<p className="title is-3">Debug section</p>
|
|
{/* {(isPending) ? <span><Spinner></Spinner> Syncronizing Patron entitlements...</span> : <span>Patreon entitlements synced.</span>} */}
|
|
{/* <p>metadataQuery as follows</p> */}
|
|
{/* <pre><code>{JSON.stringify(metadataQuery.data, null, 2)}</code></pre> */}
|
|
<p>session as follows</p>
|
|
<pre>{JSON.stringify(data, null, 2)}</pre>
|
|
{(status === 'unauthenticated') && <LoginButton></LoginButton>}
|
|
|
|
{/* <button className='button' onClick={() => refetch()}>Refetch</button> */}
|
|
<button className='button' onClick={() => update()}>Update</button>
|
|
<button className='button' onClick={() => renewJwt()}>RenewJWT</button>
|
|
</div>
|
|
|
|
|
|
{(data?.user) &&
|
|
<div className="section">
|
|
|
|
<h1 className="title is-1 mb-3">Profile</h1>
|
|
|
|
<LogoutButton></LogoutButton>
|
|
|
|
<div className="card mt-5">
|
|
<div className="card-content">
|
|
<div className="media-content">
|
|
{/* <p className="title is-4">{username}</p> */}
|
|
<p className="subtitle is-6">{data?.user?.name}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* <h2>Patronage</h2>
|
|
<div className='box'>
|
|
<p>You belong to the {patreonTier} tier. Thank you!</p>
|
|
</div> */}
|
|
|
|
<h2 className="title is-2">Patron Perks</h2>
|
|
<div className="box">
|
|
<h3 className="title is-3">Test Perk (not real)</h3>
|
|
<ProtectedRoute featureName="Test Perk" requiredUserRole="default-roles-futureporn">
|
|
<p>Hey look at you, you're granted access to this perk!</p>
|
|
</ProtectedRoute>
|
|
</div>
|
|
|
|
<div className="box">
|
|
<h3 className="title is-3">Website Shoutout</h3>
|
|
<ProtectedRoute featureName="Website shoutout" requiredUserRole="patron">
|
|
{isUsernamePublic && <span className="mr-2">{data.user.name} will be displayed on the <Link href="/patrons">/patrons page</Link></span>}
|
|
{!isUsernamePublic && <span className="mr-2">Your username will be hidden from the <Link href="/patrons">/patrons page</Link> due to your privacy setting.</span>}
|
|
{/* Users can update privacy pref at https://keycloak.fp.sbtp.xyz/realms/futureporn/account/ */}
|
|
</ProtectedRoute>
|
|
</div>
|
|
|
|
<div className='box'>
|
|
<h3 className="title is-3">Premium Content Delivery Network (CDN1)</h3>
|
|
<ProtectedRoute featureName="CDN1" requiredUserRole="patron">
|
|
<p><FontAwesomeIcon icon={faCheckCircle} className="mr-2"></FontAwesomeIcon> You have access to Futureporn's Premium CDN for reliable video playback</p>
|
|
</ProtectedRoute>
|
|
</div>
|
|
|
|
<div className='box'>
|
|
<h3 className="title is-3">Economy Content Delivery Network (CDN2)</h3>
|
|
<ProtectedRoute featureName="CDN2" requiredUserRole="default-roles-futureporn">
|
|
<p><FontAwesomeIcon icon={faCheckCircle} className="mr-2"></FontAwesomeIcon> You have access to Futureporn's Economy CDN for basic video playback</p>
|
|
</ProtectedRoute>
|
|
</div>
|
|
|
|
|
|
<div className="box">
|
|
<h3 className="title is-3">Vibrate (test)</h3>
|
|
<VibrateTest></VibrateTest>
|
|
</div>
|
|
|
|
</div>
|
|
}
|
|
</div>
|
|
)
|
|
|
|
// if (metadataQuery.isPending) return <Spinner></Spinner>;
|
|
// return <pre><code>{JSON.stringify(metadataQuery.data, null, 2)}</code></pre>
|
|
// return <p>@todo</p>
|
|
// if (!isPending) return <Spinner></Spinner>;
|
|
// if (!data) return <p>there is no data</p>;
|
|
// if (!data?.metadata) return <p>there is no data.metadata</p>;
|
|
// const { first_name, last_name } = data.metadata
|
|
// const username = formatPatronUsername(first_name, last_name)
|
|
// const { metadata } = data || {}
|
|
// const { isUsernamePublic } = metadata
|
|
|
|
|
|
// return (
|
|
// <>
|
|
|
|
// <div className="content">
|
|
// <div className="section">
|
|
// <h1 className="title is-1 mb-3">Profile</h1>
|
|
|
|
// <div className="field is-horizontal">
|
|
// <div className="field-label">Username</div>
|
|
// <p className="field is-expanded">
|
|
// {isPending &&
|
|
// <SkeletonTheme baseColor="#000" highlightColor="#000">
|
|
// <Skeleton count={1} enableAnimation={false} width="10em" />
|
|
// </SkeletonTheme>
|
|
// }
|
|
// {!isPending && <p><i>{username}</i></p>}
|
|
// </p>
|
|
// </div>
|
|
|
|
// <div className="field is-horizontal">
|
|
// <div className="field-label">User ID</div>
|
|
// <div className="field is-expanded">
|
|
// <p><i>{sessionContext.userId}</i></p>
|
|
// </div>
|
|
// </div>
|
|
|
|
// <h2 className="title is-2">Patron Perks</h2>
|
|
// <h3 className="title is-3">Website Shoutout</h3>
|
|
// <PatronRoute featureName="Website shoutout" requiredUserRole="patron">
|
|
// <div className="box">
|
|
// <span className="mr-2">Display {(!!username) ? username : <SkeletonTheme baseColor="#000" highlightColor="#000"><Skeleton count={1} enableAnimation={false} width="10em" /></SkeletonTheme>} publicly?</span>
|
|
// <input className="mr-2" type="checkbox" checked={isUsernamePublic} onChange={(evt) => attributesMutation.mutate({ isUsernamePublic: evt.target.checked })}/>
|
|
// {(attributesMutation.status === 'success') && <FontAwesomeIcon color="lime" icon={faCheckCircle}></FontAwesomeIcon>}
|
|
// {(attributesMutation.status === 'pending') && <FontAwesomeIcon icon={faSpinner}></FontAwesomeIcon>}
|
|
// {(attributesMutation.status === 'error') && <FontAwesomeIcon color="red" icon={faXmarkCircle}></FontAwesomeIcon>}
|
|
// </div>
|
|
// </PatronRoute>
|
|
|
|
// <h3 className="title is-3">Content Delivery Network (CDN)</h3>
|
|
// <PatronRoute featureName="CDN" requiredUserRole="patron">
|
|
// <p><FontAwesomeIcon icon={faCheckCircle} className="mr-2"></FontAwesomeIcon> You have access to Futureporn's CDN for reliable video playback</p>
|
|
// </PatronRoute>
|
|
|
|
|
|
// <h3 className="title is-3">Vibrate (test)</h3>
|
|
// <VibrateTest></VibrateTest>
|
|
// </div>
|
|
// </div>
|
|
|
|
// </>
|
|
// )
|
|
} |