Check user auth in api request
This commit is contained in:
@@ -23,17 +23,16 @@ export default function DropdownAccount({ messages, locale, onItemPress }: Props
|
||||
router.push(`/`, { locale: locale });
|
||||
};
|
||||
|
||||
let userAvatar =
|
||||
context.token && context.token.user ? (
|
||||
<Avatar
|
||||
size={16}
|
||||
name={context.token.user.username}
|
||||
variant="beam"
|
||||
colors={['#0A0310', '#49007E', '#FF005B', '#FF7D10', '#FFB238']}
|
||||
/>
|
||||
) : (
|
||||
<User size={16} />
|
||||
);
|
||||
let userAvatar = context.isSignedIn() ? (
|
||||
<Avatar
|
||||
size={16}
|
||||
name={context.token.user.username}
|
||||
variant="beam"
|
||||
colors={['#0A0310', '#49007E', '#FF005B', '#FF7D10', '#FFB238']}
|
||||
/>
|
||||
) : (
|
||||
<User size={16} />
|
||||
);
|
||||
|
||||
const signinItems = [
|
||||
{
|
||||
@@ -81,10 +80,10 @@ export default function DropdownAccount({ messages, locale, onItemPress }: Props
|
||||
<Dropdown>
|
||||
<DropdownTrigger>
|
||||
<Button size="sm" variant="light" startContent={userAvatar} endContent={<ChevronDown size={16} />}>
|
||||
{context.token && context.token.user ? context.token.user.username : messages.signIn}
|
||||
{context.isSignedIn() ? context.token.user.username : messages.signIn}
|
||||
</Button>
|
||||
</DropdownTrigger>
|
||||
{context.token && context.token.user ? (
|
||||
{context.isSignedIn() ? (
|
||||
<DropdownMenu aria-label="account actions when sign in">
|
||||
{signinItems.map((entry) => (
|
||||
<DropdownItem key={entry.uid} title={entry.title} startContent={entry.icon} onPress={entry.onPress} />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client';
|
||||
import { createContext, useState, useEffect } from 'react';
|
||||
import { TokenType } from '@/types/user';
|
||||
import { TokenContextType, TokenType } from '@/types/user';
|
||||
import { TokenProps } from '@/types/user';
|
||||
import { useRouter, usePathname } from '@/src/navigation';
|
||||
|
||||
@@ -15,8 +15,17 @@ function removeTokenFromLocalStorage() {
|
||||
localStorage.removeItem(LOCAL_STORAGE_KEY);
|
||||
}
|
||||
|
||||
const defaultTokenContext = {};
|
||||
const TokenContext = createContext(defaultTokenContext);
|
||||
const defaultContext = {
|
||||
token: {
|
||||
access_token: '',
|
||||
user: null,
|
||||
},
|
||||
isSignedIn: () => false,
|
||||
setToken: (token: TokenType) => {},
|
||||
storeTokenToLocalStorage,
|
||||
removeTokenFromLocalStorage,
|
||||
};
|
||||
const TokenContext = createContext<TokenContextType>(defaultContext);
|
||||
|
||||
const TokenProvider = ({ locale, children }: TokenProps) => {
|
||||
const router = useRouter();
|
||||
@@ -26,8 +35,14 @@ const TokenProvider = ({ locale, children }: TokenProps) => {
|
||||
access_token: '',
|
||||
user: null,
|
||||
});
|
||||
|
||||
const isSignedIn = () => {
|
||||
return token && token.user && token.user.username ? true : false;
|
||||
};
|
||||
|
||||
const tokenContext = {
|
||||
token,
|
||||
isSignedIn,
|
||||
setToken,
|
||||
storeTokenToLocalStorage,
|
||||
removeTokenFromLocalStorage,
|
||||
|
||||
@@ -18,7 +18,7 @@ export default function AccountPage({ messages, locale }: Props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
{context.token && context.token.user && (
|
||||
{context.isSignedIn() && (
|
||||
<Card className="w-[600px] mt-16 mx-3">
|
||||
<CardHeader className="flex gap-6">
|
||||
<Avatar
|
||||
|
||||
@@ -20,8 +20,11 @@ export default function ProjectsPage({ messages, locale }: Props) {
|
||||
|
||||
useEffect(() => {
|
||||
async function fetchDataEffect() {
|
||||
if (!context.isSignedIn()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const data = await fetchProjects();
|
||||
const data = await fetchProjects(context.token.access_token);
|
||||
setProjects(data);
|
||||
} catch (error: any) {
|
||||
console.error('Error in effect:', error.message);
|
||||
@@ -29,14 +32,14 @@ export default function ProjectsPage({ messages, locale }: Props) {
|
||||
}
|
||||
|
||||
fetchDataEffect();
|
||||
}, []);
|
||||
}, [context]);
|
||||
|
||||
// dialog
|
||||
const [isNeedSignedInDialogOpen, setIsNeedSignedInDialogOpen] = useState(false);
|
||||
const [isProjectDialogOpen, setIsProjectDialogOpen] = useState(false);
|
||||
const [editingProject, setEditingProject] = useState<ProjectType | null>(null);
|
||||
const openDialogForCreate = () => {
|
||||
if (!context.token || !context.token.user) {
|
||||
if (!context.isSignedIn()) {
|
||||
setIsNeedSignedInDialogOpen(true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
TableRow,
|
||||
TableCell,
|
||||
Button,
|
||||
Chip,
|
||||
DropdownTrigger,
|
||||
Dropdown,
|
||||
DropdownMenu,
|
||||
@@ -29,8 +30,8 @@ type Props = {
|
||||
export default function ProjectsTable({ projects, onEditProject, onDeleteProject, messages, locale }: Props) {
|
||||
const headerColumns = [
|
||||
{ name: messages.id, uid: 'id', sortable: true },
|
||||
{ name: messages.publicity, uid: 'isPublic', sortable: true },
|
||||
{ name: messages.name, uid: 'name', sortable: true },
|
||||
{ name: messages.detail, uid: 'detail', sortable: true },
|
||||
{ name: messages.lastUpdate, uid: 'updatedAt', sortable: true },
|
||||
{ name: messages.actions, uid: 'actions' },
|
||||
];
|
||||
@@ -60,18 +61,19 @@ export default function ProjectsTable({ projects, onEditProject, onDeleteProject
|
||||
switch (columnKey) {
|
||||
case 'id':
|
||||
return <span>{cellValue}</span>;
|
||||
case 'isPublic':
|
||||
return cellValue ? <Chip size="sm">{messages.public}</Chip> : <></>;
|
||||
case 'name':
|
||||
const maxLength = 30;
|
||||
const truncatedDetail = truncateText(project.detail, maxLength);
|
||||
return (
|
||||
<Link href={`/projects/${project.id}/home`} locale={locale} className={NextUiLinkClasses}>
|
||||
{cellValue}
|
||||
</Link>
|
||||
);
|
||||
case 'detail':
|
||||
const maxLength = 20;
|
||||
const truncatedValue = truncateText(cellValue, maxLength);
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<div>{truncatedValue}</div>
|
||||
<div>
|
||||
<Link href={`/projects/${project.id}/home`} locale={locale} className={NextUiLinkClasses}>
|
||||
{cellValue}
|
||||
</Link>
|
||||
<div className="text-xs text-default-500">
|
||||
<div>{truncatedDetail}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
case 'updatedAt':
|
||||
|
||||
@@ -30,7 +30,6 @@ export default function RunsTable({ projectId, runs, onDeleteRun, messages, loca
|
||||
const headerColumns = [
|
||||
{ name: messages.id, uid: 'id', sortable: true },
|
||||
{ name: messages.name, uid: 'name', sortable: true },
|
||||
{ name: messages.description, uid: 'description', sortable: true },
|
||||
{ name: messages.lastUpdate, uid: 'updatedAt', sortable: true },
|
||||
{ name: messages.actions, uid: 'actions' },
|
||||
];
|
||||
@@ -61,17 +60,16 @@ export default function RunsTable({ projectId, runs, onDeleteRun, messages, loca
|
||||
case 'id':
|
||||
return <span>{cellValue}</span>;
|
||||
case 'name':
|
||||
const maxLength = 30;
|
||||
const truncatedDescription = truncateText(run.description, maxLength);
|
||||
return (
|
||||
<Link href={`/projects/${projectId}/runs/${run.id}`} locale={locale} className={NextUiLinkClasses}>
|
||||
{cellValue}
|
||||
</Link>
|
||||
);
|
||||
case 'detail':
|
||||
const maxLength = 20;
|
||||
const truncatedValue = truncateText(cellValue, maxLength);
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
<div>{truncatedValue}</div>
|
||||
<div>
|
||||
<Link href={`/projects/${projectId}/runs/${run.id}`} locale={locale} className={NextUiLinkClasses}>
|
||||
{cellValue}
|
||||
</Link>
|
||||
<div className="text-xs text-default-500">
|
||||
<div>{truncatedDescription}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
case 'updatedAt':
|
||||
|
||||
@@ -10,6 +10,7 @@ export default function Page(params: { locale: string }) {
|
||||
editProject: t('edit_project'),
|
||||
deleteProject: t('delete_project'),
|
||||
id: t('id'),
|
||||
publicity: t('publicity'),
|
||||
name: t('name'),
|
||||
detail: t('detail'),
|
||||
lastUpdate: t('last_update'),
|
||||
|
||||
@@ -4,7 +4,7 @@ const apiServer = Config.apiServer;
|
||||
/**
|
||||
* fetch project records
|
||||
*/
|
||||
async function fetchProjects() {
|
||||
async function fetchProjects(jwt: string) {
|
||||
const url = `${apiServer}/projects`;
|
||||
|
||||
try {
|
||||
@@ -12,6 +12,7 @@ async function fetchProjects() {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: jwt,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user