mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 20:36:40 +07:00
fixed user hydration
This commit is contained in:
parent
ed9694c246
commit
75dc20ca0b
13 changed files with 194 additions and 95 deletions
|
@ -1,9 +1,19 @@
|
||||||
import React, { createElement, FC, Fragment, memo, ReactNode, useCallback, useMemo, useState } from 'react';
|
import React, {
|
||||||
|
createElement,
|
||||||
|
FC,
|
||||||
|
Fragment,
|
||||||
|
memo,
|
||||||
|
ReactNode,
|
||||||
|
useCallback,
|
||||||
|
useMemo,
|
||||||
|
useState,
|
||||||
|
} from 'react';
|
||||||
|
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import { CommentForm } from '~/components/comment/CommentForm';
|
import { CommentForm } from '~/components/comment/CommentForm';
|
||||||
|
import { Authorized } from '~/components/containers/Authorized';
|
||||||
import { Group } from '~/components/containers/Group';
|
import { Group } from '~/components/containers/Group';
|
||||||
import { AudioPlayer } from '~/components/media/AudioPlayer';
|
import { AudioPlayer } from '~/components/media/AudioPlayer';
|
||||||
import { COMMENT_BLOCK_RENDERERS } from '~/constants/comment';
|
import { COMMENT_BLOCK_RENDERERS } from '~/constants/comment';
|
||||||
|
@ -28,7 +38,15 @@ interface IProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CommentContent: FC<IProps> = memo(
|
const CommentContent: FC<IProps> = memo(
|
||||||
({ comment, canEdit, nodeId, saveComment, onDelete, onShowImageModal, prefix }) => {
|
({
|
||||||
|
comment,
|
||||||
|
canEdit,
|
||||||
|
nodeId,
|
||||||
|
saveComment,
|
||||||
|
onDelete,
|
||||||
|
onShowImageModal,
|
||||||
|
prefix,
|
||||||
|
}) => {
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
|
|
||||||
const startEditing = useCallback(() => setIsEditing(true), [setIsEditing]);
|
const startEditing = useCallback(() => setIsEditing(true), [setIsEditing]);
|
||||||
|
@ -38,11 +56,13 @@ const CommentContent: FC<IProps> = memo(
|
||||||
() =>
|
() =>
|
||||||
reduce(
|
reduce(
|
||||||
(group, file) =>
|
(group, file) =>
|
||||||
file.type ? assocPath([file.type], append(file, group[file.type]), group) : group,
|
file.type
|
||||||
|
? assocPath([file.type], append(file, group[file.type]), group)
|
||||||
|
: group,
|
||||||
{} as Record<UploadType, IFile[]>,
|
{} as Record<UploadType, IFile[]>,
|
||||||
comment.files
|
comment.files,
|
||||||
),
|
),
|
||||||
[comment]
|
[comment],
|
||||||
);
|
);
|
||||||
|
|
||||||
const onLockClick = useCallback(() => {
|
const onLockClick = useCallback(() => {
|
||||||
|
@ -50,8 +70,9 @@ const CommentContent: FC<IProps> = memo(
|
||||||
}, [comment, onDelete]);
|
}, [comment, onDelete]);
|
||||||
|
|
||||||
const menu = useMemo(
|
const menu = useMemo(
|
||||||
() => canEdit && <CommentMenu onDelete={onLockClick} onEdit={startEditing} />,
|
() =>
|
||||||
[canEdit, startEditing, onLockClick]
|
canEdit && <CommentMenu onDelete={onLockClick} onEdit={startEditing} />,
|
||||||
|
[canEdit, startEditing, onLockClick],
|
||||||
);
|
);
|
||||||
|
|
||||||
const blocks = useMemo(
|
const blocks = useMemo(
|
||||||
|
@ -59,7 +80,7 @@ const CommentContent: FC<IProps> = memo(
|
||||||
!!comment.text.trim()
|
!!comment.text.trim()
|
||||||
? formatCommentText(path(['user', 'username'], comment), comment.text)
|
? formatCommentText(path(['user', 'username'], comment), comment.text)
|
||||||
: [],
|
: [],
|
||||||
[comment]
|
[comment],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isEditing) {
|
if (isEditing) {
|
||||||
|
@ -78,17 +99,22 @@ const CommentContent: FC<IProps> = memo(
|
||||||
{!!prefix && <div className={styles.prefix}>{prefix}</div>}
|
{!!prefix && <div className={styles.prefix}>{prefix}</div>}
|
||||||
{comment.text.trim() && (
|
{comment.text.trim() && (
|
||||||
<Group className={classnames(styles.block, styles.block_text)}>
|
<Group className={classnames(styles.block, styles.block_text)}>
|
||||||
{menu}
|
<Authorized>{menu}</Authorized>
|
||||||
|
|
||||||
<Group className={styles.renderers}>
|
<Group className={styles.renderers}>
|
||||||
{blocks.map(
|
{blocks.map(
|
||||||
(block, key) =>
|
(block, key) =>
|
||||||
COMMENT_BLOCK_RENDERERS[block.type] &&
|
COMMENT_BLOCK_RENDERERS[block.type] &&
|
||||||
createElement(COMMENT_BLOCK_RENDERERS[block.type], { block, key })
|
createElement(COMMENT_BLOCK_RENDERERS[block.type], {
|
||||||
|
block,
|
||||||
|
key,
|
||||||
|
}),
|
||||||
)}
|
)}
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<div className={styles.date}>{getPrettyDate(comment.created_at)}</div>
|
<div className={styles.date}>
|
||||||
|
{getPrettyDate(comment.created_at)}
|
||||||
|
</div>
|
||||||
</Group>
|
</Group>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -102,32 +128,45 @@ const CommentContent: FC<IProps> = memo(
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{groupped.image.map((file, index) => (
|
{groupped.image.map((file, index) => (
|
||||||
<div key={file.id} onClick={() => onShowImageModal(groupped.image, index)}>
|
<div
|
||||||
<img src={getURL(file, ImagePresets['600'])} alt={file.name} />
|
key={file.id}
|
||||||
|
onClick={() => onShowImageModal(groupped.image, index)}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={getURL(file, ImagePresets['600'])}
|
||||||
|
alt={file.name}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.date}>{getPrettyDate(comment.created_at)}</div>
|
<div className={styles.date}>
|
||||||
|
{getPrettyDate(comment.created_at)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{groupped.audio && groupped.audio.length > 0 && (
|
{groupped.audio && groupped.audio.length > 0 && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{groupped.audio.map(file => (
|
{groupped.audio.map((file) => (
|
||||||
<div className={classnames(styles.block, styles.block_audio)} key={file.id}>
|
<div
|
||||||
|
className={classnames(styles.block, styles.block_audio)}
|
||||||
|
key={file.id}
|
||||||
|
>
|
||||||
{menu}
|
{menu}
|
||||||
|
|
||||||
<AudioPlayer file={file} />
|
<AudioPlayer file={file} />
|
||||||
|
|
||||||
<div className={styles.date}>{getPrettyDate(comment.created_at)}</div>
|
<div className={styles.date}>
|
||||||
|
{getPrettyDate(comment.created_at)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export { CommentContent };
|
export { CommentContent };
|
||||||
|
|
|
@ -1,15 +1,20 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
|
||||||
|
import { observer } from 'mobx-react-lite';
|
||||||
|
|
||||||
import { useAuth } from '~/hooks/auth/useAuth';
|
import { useAuth } from '~/hooks/auth/useAuth';
|
||||||
|
|
||||||
interface IProps {}
|
interface IProps {
|
||||||
|
// don't wait for user refetch, trust hydration
|
||||||
|
hydratedOnly?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
const Authorized: FC<IProps> = ({ children }) => {
|
const Authorized: FC<IProps> = observer(({ children, hydratedOnly }) => {
|
||||||
const { isUser } = useAuth();
|
const { isUser, fetched } = useAuth();
|
||||||
|
|
||||||
if (!isUser) return null;
|
if (!isUser || (!hydratedOnly && !fetched)) return null;
|
||||||
|
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
};
|
});
|
||||||
|
|
||||||
export { Authorized };
|
export { Authorized };
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import React, { FC, Fragment } from 'react';
|
import React, { FC, Fragment } from 'react';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { observer } from 'mobx-react-lite';
|
||||||
|
|
||||||
import { FlowCell } from '~/components/flow/FlowCell';
|
import { FlowCell } from '~/components/flow/FlowCell';
|
||||||
import { flowDisplayToPreset, URLS } from '~/constants/urls';
|
import { flowDisplayToPreset, URLS } from '~/constants/urls';
|
||||||
|
import { useAuth } from '~/hooks/auth/useAuth';
|
||||||
import { FlowDisplay, IFlowNode, INode } from '~/types';
|
import { FlowDisplay, IFlowNode, INode } from '~/types';
|
||||||
import { IUser } from '~/types/auth';
|
import { IUser } from '~/types/auth';
|
||||||
import { getURLFromString } from '~/utils/dom';
|
import { getURLFromString } from '~/utils/dom';
|
||||||
|
@ -17,28 +19,38 @@ interface Props {
|
||||||
onChangeCellView: (id: INode['id'], flow: FlowDisplay) => void;
|
onChangeCellView: (id: INode['id'], flow: FlowDisplay) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FlowGrid: FC<Props> = ({ user, nodes, onChangeCellView }) => {
|
export const FlowGrid: FC<Props> = observer(
|
||||||
|
({ user, nodes, onChangeCellView }) => {
|
||||||
|
const { fetched, isUser } = useAuth();
|
||||||
|
|
||||||
if (!nodes) {
|
if (!nodes) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{nodes.map(node => (
|
{nodes.map((node) => (
|
||||||
<div className={classNames(styles.cell, styles[node.flow.display])} key={node.id}>
|
<div
|
||||||
|
className={classNames(styles.cell, styles[node.flow.display])}
|
||||||
|
key={node.id}
|
||||||
|
>
|
||||||
<FlowCell
|
<FlowCell
|
||||||
id={node.id}
|
id={node.id}
|
||||||
color={node.flow.dominant_color}
|
color={node.flow.dominant_color}
|
||||||
to={URLS.NODE_URL(node.id)}
|
to={URLS.NODE_URL(node.id)}
|
||||||
image={getURLFromString(node.thumbnail, flowDisplayToPreset[node.flow.display])}
|
image={getURLFromString(
|
||||||
|
node.thumbnail,
|
||||||
|
flowDisplayToPreset[node.flow.display],
|
||||||
|
)}
|
||||||
flow={node.flow}
|
flow={node.flow}
|
||||||
text={node.description}
|
text={node.description}
|
||||||
title={node.title}
|
title={node.title}
|
||||||
canEdit={canEditNode(node, user)}
|
canEdit={fetched && isUser && canEditNode(node, user)}
|
||||||
onChangeCellView={onChangeCellView}
|
onChangeCellView={onChangeCellView}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
};
|
},
|
||||||
|
);
|
||||||
|
|
|
@ -4,7 +4,7 @@ import classNames from 'classnames';
|
||||||
|
|
||||||
import styles from './styles.module.scss';
|
import styles from './styles.module.scss';
|
||||||
|
|
||||||
interface SeparatedMenuProps {
|
export interface SeparatedMenuProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ const SeparatedMenu: FC<SeparatedMenuProps> = ({ children, className }) => {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (Array.isArray(children) ? children : [children]).filter(it => it);
|
return (Array.isArray(children) ? children : [children]).filter((it) => it);
|
||||||
}, [children]);
|
}, [children]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,6 +2,7 @@ import React, { memo, VFC } from 'react';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { Authorized } from '~/components/containers/Authorized';
|
||||||
import { Icon } from '~/components/input/Icon';
|
import { Icon } from '~/components/input/Icon';
|
||||||
import { SeparatedMenu } from '~/components/menu/SeparatedMenu';
|
import { SeparatedMenu } from '~/components/menu/SeparatedMenu';
|
||||||
import { NodeEditMenu } from '~/components/node/NodeEditMenu';
|
import { NodeEditMenu } from '~/components/node/NodeEditMenu';
|
||||||
|
@ -76,6 +77,7 @@ const NodeTitle: VFC<IProps> = memo(
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Authorized>
|
||||||
<SeparatedMenu className={styles.buttons}>
|
<SeparatedMenu className={styles.buttons}>
|
||||||
{canEdit && (
|
{canEdit && (
|
||||||
<NodeEditMenu
|
<NodeEditMenu
|
||||||
|
@ -107,6 +109,7 @@ const NodeTitle: VFC<IProps> = memo(
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</SeparatedMenu>
|
</SeparatedMenu>
|
||||||
|
</Authorized>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
import { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import isBefore from 'date-fns/isBefore';
|
import isBefore from 'date-fns/isBefore';
|
||||||
|
@ -16,7 +16,6 @@ import { URLS } from '~/constants/urls';
|
||||||
import { useAuth } from '~/hooks/auth/useAuth';
|
import { useAuth } from '~/hooks/auth/useAuth';
|
||||||
import { useScrollTop } from '~/hooks/dom/useScrollTop';
|
import { useScrollTop } from '~/hooks/dom/useScrollTop';
|
||||||
import { useFlow } from '~/hooks/flow/useFlow';
|
import { useFlow } from '~/hooks/flow/useFlow';
|
||||||
import { useGetLabStats } from '~/hooks/lab/useGetLabStats';
|
|
||||||
import { useModal } from '~/hooks/modal/useModal';
|
import { useModal } from '~/hooks/modal/useModal';
|
||||||
import { useUpdates } from '~/hooks/updates/useUpdates';
|
import { useUpdates } from '~/hooks/updates/useUpdates';
|
||||||
import { useSidebar } from '~/utils/providers/SidebarProvider';
|
import { useSidebar } from '~/utils/providers/SidebarProvider';
|
||||||
|
@ -66,8 +65,13 @@ const Header: FC<HeaderProps> = observer(() => {
|
||||||
|
|
||||||
<Filler className={styles.filler} />
|
<Filler className={styles.filler} />
|
||||||
|
|
||||||
<nav className={styles.plugs}>
|
<nav
|
||||||
<Authorized>
|
className={classNames(styles.plugs, {
|
||||||
|
// [styles.active]: isHydrated && fetched,
|
||||||
|
[styles.active]: true,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<Authorized hydratedOnly>
|
||||||
<Anchor
|
<Anchor
|
||||||
className={classNames(styles.item, {
|
className={classNames(styles.item, {
|
||||||
[styles.has_dot]: hasFlowUpdates,
|
[styles.has_dot]: hasFlowUpdates,
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
@keyframes appear {
|
@keyframes appear {
|
||||||
from {
|
from {
|
||||||
transform: translate(0, -$header_height);
|
opacity: 0;
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
transform: translate(0, 0);
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,12 @@
|
||||||
user-select: none;
|
user-select: none;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 250ms;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
@include tablet {
|
@include tablet {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
|
@ -16,5 +16,6 @@ export const useAuth = () => {
|
||||||
setToken: auth.setToken,
|
setToken: auth.setToken,
|
||||||
isTester: auth.isTester,
|
isTester: auth.isTester,
|
||||||
setIsTester: auth.setIsTester,
|
setIsTester: auth.setIsTester,
|
||||||
|
fetched: auth.fetched,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,11 +10,19 @@ import { IUser } from '~/types/auth';
|
||||||
import { showErrorToast } from '~/utils/errors/showToast';
|
import { showErrorToast } from '~/utils/errors/showToast';
|
||||||
|
|
||||||
export const useUser = () => {
|
export const useUser = () => {
|
||||||
const { token, setUser } = useAuthStore();
|
const { token, setUser, setFetched, user } = useAuthStore();
|
||||||
const { data, mutate } = useSWR(token ? API.USER.ME : null, () => apiAuthGetUser(), {
|
const { data, mutate } = useSWR(
|
||||||
onSuccess: data => setUser(data?.user || EMPTY_USER),
|
token ? API.USER.ME : null,
|
||||||
onError: error => showErrorToast(error),
|
() => apiAuthGetUser(),
|
||||||
});
|
{
|
||||||
|
onSuccess: (data) => {
|
||||||
|
setUser(data?.user || EMPTY_USER);
|
||||||
|
setFetched(true);
|
||||||
|
},
|
||||||
|
onError: (error) => showErrorToast(error),
|
||||||
|
fallbackData: { user },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const update = useCallback(
|
const update = useCallback(
|
||||||
async (user: Partial<IUser>, revalidate?: boolean) => {
|
async (user: Partial<IUser>, revalidate?: boolean) => {
|
||||||
|
@ -25,7 +33,7 @@ export const useUser = () => {
|
||||||
|
|
||||||
await mutate({ ...data, user: { ...data.user, ...user } }, revalidate);
|
await mutate({ ...data, user: { ...data.user, ...user } }, revalidate);
|
||||||
},
|
},
|
||||||
[data, mutate]
|
[data, mutate],
|
||||||
);
|
);
|
||||||
|
|
||||||
return { user: data?.user || EMPTY_USER, update };
|
return { user: data?.user || EMPTY_USER, update };
|
||||||
|
|
|
@ -4,12 +4,24 @@ import { useUser } from '~/hooks/auth/useUser';
|
||||||
import { INode } from '~/types';
|
import { INode } from '~/types';
|
||||||
import { canEditNode, canLikeNode, canStarNode } from '~/utils/node';
|
import { canEditNode, canLikeNode, canStarNode } from '~/utils/node';
|
||||||
|
|
||||||
|
import { useAuth } from '../auth/useAuth';
|
||||||
|
|
||||||
export const useNodePermissions = (node?: INode) => {
|
export const useNodePermissions = (node?: INode) => {
|
||||||
const { user } = useUser();
|
const { user } = useUser();
|
||||||
|
const { fetched, isUser } = useAuth();
|
||||||
|
|
||||||
const edit = useMemo(() => canEditNode(node, user), [node, user]);
|
const edit = useMemo(
|
||||||
const like = useMemo(() => canLikeNode(node, user), [node, user]);
|
() => fetched && isUser && canEditNode(node, user),
|
||||||
const star = useMemo(() => canStarNode(node, user), [node, user]);
|
[node, user, fetched, isUser],
|
||||||
|
);
|
||||||
|
const like = useMemo(
|
||||||
|
() => fetched && isUser && canLikeNode(node, user),
|
||||||
|
[node, user, fetched, isUser],
|
||||||
|
);
|
||||||
|
const star = useMemo(
|
||||||
|
() => fetched && isUser && canStarNode(node, user),
|
||||||
|
[node, user, fetched, isUser],
|
||||||
|
);
|
||||||
|
|
||||||
return [edit, like, star];
|
return [edit, like, star];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
|
|
||||||
|
import { observer } from 'mobx-react-lite';
|
||||||
|
|
||||||
import { Superpower } from '~/components/boris/Superpower';
|
import { Superpower } from '~/components/boris/Superpower';
|
||||||
import { ScrollHelperBottom } from '~/components/common/ScrollHelperBottom';
|
import { ScrollHelperBottom } from '~/components/common/ScrollHelperBottom';
|
||||||
import { Card } from '~/components/containers/Card';
|
import { Card } from '~/components/containers/Card';
|
||||||
|
@ -18,7 +20,7 @@ import styles from './styles.module.scss';
|
||||||
|
|
||||||
type IProps = {};
|
type IProps = {};
|
||||||
|
|
||||||
const NodeLayout: FC<IProps> = () => {
|
const NodeLayout: FC<IProps> = observer(() => {
|
||||||
const { node, isLoading, update } = useNodeContext();
|
const { node, isLoading, update } = useNodeContext();
|
||||||
const { head, block } = useNodeBlocks(node, isLoading);
|
const { head, block } = useNodeBlocks(node, isLoading);
|
||||||
const [canEdit, canLike, canStar] = useNodePermissions(node);
|
const [canEdit, canLike, canStar] = useNodePermissions(node);
|
||||||
|
@ -70,6 +72,6 @@ const NodeLayout: FC<IProps> = () => {
|
||||||
</Superpower>
|
</Superpower>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export { NodeLayout };
|
export { NodeLayout };
|
||||||
|
|
|
@ -9,6 +9,7 @@ export class AuthStore {
|
||||||
token: string = '';
|
token: string = '';
|
||||||
user: IUser = EMPTY_USER;
|
user: IUser = EMPTY_USER;
|
||||||
isTesterInternal: boolean = false;
|
isTesterInternal: boolean = false;
|
||||||
|
fetched = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
|
@ -46,4 +47,8 @@ export class AuthStore {
|
||||||
this.token = '';
|
this.token = '';
|
||||||
this.setUser(EMPTY_USER);
|
this.setUser(EMPTY_USER);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
setFetched = (fetched: boolean) => {
|
||||||
|
this.fetched = fetched;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { createContext, FC, useContext } from 'react';
|
import { createContext, FC, useContext } from 'react';
|
||||||
|
|
||||||
import { observer } from 'mobx-react-lite';
|
import { observer } from 'mobx-react-lite';
|
||||||
|
import { boolean } from 'yup';
|
||||||
|
|
||||||
import { EMPTY_USER } from '~/constants/auth';
|
import { EMPTY_USER } from '~/constants/auth';
|
||||||
import { useAuth } from '~/hooks/auth/useAuth';
|
import { useAuth } from '~/hooks/auth/useAuth';
|
||||||
|
@ -18,6 +19,7 @@ const AuthContext = createContext<AuthProviderContextType>({
|
||||||
logout: () => {},
|
logout: () => {},
|
||||||
login: async () => EMPTY_USER,
|
login: async () => EMPTY_USER,
|
||||||
setToken: () => {},
|
setToken: () => {},
|
||||||
|
fetched: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const AuthProvider: FC = observer(({ children }) => {
|
export const AuthProvider: FC = observer(({ children }) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue