[questions][feat] add useProtectedCallback hook (#472)

This commit is contained in:
Jeff Sieu
2022-10-31 14:31:56 +08:00
committed by GitHub
parent ade6d1d88d
commit 538fa5ccf7
11 changed files with 179 additions and 44 deletions

View File

@@ -5,6 +5,7 @@ import { Fragment, useRef, useState } from 'react';
import { Menu, Transition } from '@headlessui/react';
import { CheckIcon, HeartIcon } from '@heroicons/react/20/solid';
import { useProtectedCallback } from '~/utils/questions/useProtectedCallback';
import { trpc } from '~/utils/trpc';
export type AddToListDropdownProps = {
@@ -85,14 +86,16 @@ export default function AddToListDropdown({
});
};
const handleMenuButtonClick = useProtectedCallback(() => {
addClickOutsideListener();
setMenuOpened(!menuOpened);
});
const CustomMenuButton = ({ children }: PropsWithChildren<unknown>) => (
<button
className="focus:ring-primary-500 inline-flex w-full justify-center rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-slate-100"
type="button"
onClick={() => {
addClickOutsideListener();
setMenuOpened(!menuOpened);
}}>
onClick={handleMenuButtonClick}>
{children}
</button>
);

View File

@@ -6,6 +6,8 @@ import {
} from '@heroicons/react/24/outline';
import { TextInput } from '@tih/ui';
import { useProtectedCallback } from '~/utils/questions/useProtectedCallback';
import ContributeQuestionDialog from './ContributeQuestionDialog';
import type { ContributeQuestionFormProps } from './forms/ContributeQuestionForm';
@@ -23,9 +25,9 @@ export default function ContributeQuestionCard({
setShowDraftDialog(false);
};
const handleOpenContribute = () => {
const handleOpenContribute = useProtectedCallback(() => {
setShowDraftDialog(true);
};
});
return (
<div className="w-full">

View File

@@ -4,6 +4,8 @@ import type { Vote } from '@prisma/client';
import type { ButtonSize } from '@tih/ui';
import { Button } from '@tih/ui';
import { useProtectedCallback } from '~/utils/questions/useProtectedCallback';
export type BackendVote = {
id: string;
vote: Vote;
@@ -31,6 +33,15 @@ export default function VotingButtons({
vote?.vote === 'UPVOTE' ? 'secondary' : 'tertiary';
const downvoteButtonVariant =
vote?.vote === 'DOWNVOTE' ? 'secondary' : 'tertiary';
const handleUpvoteClick = useProtectedCallback(() => {
onUpvote();
});
const handleDownvoteClick = useProtectedCallback(() => {
onDownvote();
});
return (
<div className="flex flex-col items-center">
<Button
@@ -42,7 +53,7 @@ export default function VotingButtons({
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
onUpvote();
handleUpvoteClick();
}}
/>
<p>{upvoteCount}</p>
@@ -55,7 +66,7 @@ export default function VotingButtons({
onClick={(event) => {
event.preventDefault();
event.stopPropagation();
onDownvote();
handleDownvoteClick();
}}
/>
</div>

View File

@@ -9,6 +9,7 @@ import {
import type { QuestionsQuestionType } from '@prisma/client';
import { Button } from '@tih/ui';
import { useProtectedCallback } from '~/utils/questions/useProtectedCallback';
import { useQuestionVote } from '~/utils/questions/useVote';
import AddToListDropdown from '../../AddToListDropdown';
@@ -168,6 +169,10 @@ export default function BaseQuestionCard({
return countryCount;
}, [countries]);
const handleCreateEncounterClick = useProtectedCallback(() => {
setShowReceivedForm(true);
});
const cardContent = (
<>
{showVoteButtons && (
@@ -244,10 +249,7 @@ export default function BaseQuestionCard({
label={createEncounterButtonText}
size="sm"
variant="tertiary"
onClick={(event) => {
event.preventDefault();
setShowReceivedForm(true);
}}
onClick={handleCreateEncounterClick}
/>
)}
</div>

View File

@@ -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>
);
}

View File

@@ -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>
);
}