[questions][feat] add useProtectedCallback hook (#472)
parent
ade6d1d88d
commit
538fa5ccf7
@ -0,0 +1,40 @@
|
||||
import type { PropsWithChildren } from 'react';
|
||||
import { createContext, useState } from 'react';
|
||||
|
||||
import ProtectedDialog from './ProtectedDialog';
|
||||
|
||||
export type ProtectedContextData = {
|
||||
showDialog: () => void;
|
||||
};
|
||||
|
||||
export const ProtectedContext = createContext<ProtectedContextData>({
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
showDialog: () => {},
|
||||
});
|
||||
|
||||
export type ProtectedContextProviderProps = PropsWithChildren<
|
||||
Record<string, unknown>
|
||||
>;
|
||||
|
||||
export default function ProtectedContextProvider({
|
||||
children,
|
||||
}: ProtectedContextProviderProps) {
|
||||
const [show, setShow] = useState(false);
|
||||
|
||||
return (
|
||||
<ProtectedContext.Provider
|
||||
value={{
|
||||
showDialog: () => {
|
||||
setShow(true);
|
||||
},
|
||||
}}>
|
||||
{children}
|
||||
<ProtectedDialog
|
||||
show={show}
|
||||
onClose={() => {
|
||||
setShow(false);
|
||||
}}
|
||||
/>
|
||||
</ProtectedContext.Provider>
|
||||
);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
import { signIn } from 'next-auth/react';
|
||||
import { Button, Dialog } from '@tih/ui';
|
||||
|
||||
export type ProtectedDialogProps = {
|
||||
onClose: () => void;
|
||||
show: boolean;
|
||||
};
|
||||
|
||||
export default function ProtectedDialog({
|
||||
show,
|
||||
onClose,
|
||||
}: ProtectedDialogProps) {
|
||||
const handlePrimaryClick = () => {
|
||||
signIn();
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
isShown={show}
|
||||
primaryButton={
|
||||
<Button
|
||||
label="Sign in"
|
||||
variant="primary"
|
||||
onClick={handlePrimaryClick}
|
||||
/>
|
||||
}
|
||||
secondaryButton={
|
||||
<Button label="Cancel" variant="tertiary" onClick={onClose} />
|
||||
}
|
||||
title="Sign in to continue"
|
||||
onClose={onClose}>
|
||||
<p>This action requires you to be signed in.</p>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { useCallback, useContext } from 'react';
|
||||
|
||||
import { ProtectedContext } from '~/components/questions/protected/ProtectedContextProvider';
|
||||
|
||||
export const useProtectedCallback = <T extends Array<unknown>, U>(
|
||||
callback: (...args: T) => U,
|
||||
) => {
|
||||
const { showDialog } = useContext(ProtectedContext);
|
||||
const { status } = useSession();
|
||||
|
||||
const protectedCallback = useCallback(
|
||||
(...args: T) => {
|
||||
if (status === 'authenticated') {
|
||||
return callback(...args);
|
||||
}
|
||||
showDialog();
|
||||
},
|
||||
[callback, showDialog, status],
|
||||
);
|
||||
return protectedCallback;
|
||||
};
|
Loading…
Reference in new issue