Skip to content

Commit 39f383c

Browse files
authored
demo: signin logic fixes and various UI fixes (#12)
1 parent 4c757c7 commit 39f383c

File tree

8 files changed

+104
-64
lines changed

8 files changed

+104
-64
lines changed

samples/todo/components/AuthGuard.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ export default function AuthGuard({ children }: Props) {
88
const { status } = useSession();
99
if (status === 'loading') {
1010
return <p>Loading...</p>;
11-
}
12-
if (status === 'unauthenticated') {
11+
} else if (status === 'unauthenticated') {
1312
signIn();
13+
return <></>;
14+
} else {
15+
return <>{children}</>;
1416
}
15-
return <>{children}</>;
1617
}

samples/todo/components/Spaces.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default function Spaces() {
66
const spaces = find();
77

88
return (
9-
<ul className="flex flex-wrap space-x-4">
9+
<ul className="flex flex-wrap gap-4">
1010
{spaces.data?.map((space) => (
1111
<li
1212
className="card w-80 h-32 shadow-xl text-gray-600 cursor-pointer hover:bg-gray-50 border"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import moment from 'moment';
2+
3+
type Props = {
4+
value: { createdAt: Date; updatedAt: Date; completedAt?: Date | null };
5+
};
6+
7+
export default function TimeInfo({ value }: Props) {
8+
return (
9+
<p className="text-sm text-gray-500">
10+
{value.completedAt
11+
? `Completed ${moment(value.completedAt).fromNow()}`
12+
: value.createdAt === value.updatedAt
13+
? `Created ${moment(value.createdAt).fromNow()}`
14+
: `Updated ${moment(value.updatedAt).fromNow()}`}
15+
</p>
16+
);
17+
}

samples/todo/components/Todo.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { TrashIcon } from '@heroicons/react/24/outline';
22
import { useTodo } from '@zenstackhq/runtime/hooks';
33
import { Todo, User } from '@zenstackhq/runtime/types';
4-
import moment from 'moment';
54
import { ChangeEvent, useEffect, useState } from 'react';
65
import Avatar from './Avatar';
6+
import TimeInfo from './TimeInfo';
77

88
type Props = {
99
value: Todo & { owner: User };
@@ -64,13 +64,7 @@ export default function Component({ value, updated, deleted }: Props) {
6464
</div>
6565
</div>
6666
<div className="flex justify-end w-full space-x-2">
67-
<p className="text-sm text-gray-500">
68-
{value.completedAt
69-
? `Completed ${moment(value.completedAt).fromNow()}`
70-
: value.createdAt === value.updatedAt
71-
? `Created ${moment(value.createdAt).fromNow()}`
72-
: `Updated ${moment(value.updatedAt).fromNow()}`}
73-
</p>
67+
<TimeInfo value={value} />
7468
<Avatar user={value.owner} size={18} />
7569
</div>
7670
</div>
Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,77 @@
11
import Image from 'next/image';
22
import { List } from '@zenstackhq/runtime/types';
33
import { customAlphabet } from 'nanoid';
4-
import { LockClosedIcon } from '@heroicons/react/24/outline';
4+
import { LockClosedIcon, TrashIcon } from '@heroicons/react/24/outline';
55
import { User } from 'next-auth';
66
import Avatar from './Avatar';
77
import Link from 'next/link';
88
import { useRouter } from 'next/router';
9+
import { useList } from '@zenstackhq/runtime/hooks';
10+
import TimeInfo from './TimeInfo';
911

1012
type Props = {
1113
value: List & { owner: User };
14+
deleted?: (value: List) => void;
1215
};
1316

14-
export default function TodoList({ value }: Props) {
17+
export default function TodoList({ value, deleted }: Props) {
1518
const router = useRouter();
19+
20+
const { del } = useList();
21+
22+
const deleteList = async () => {
23+
if (confirm('Are you sure to delete this list?')) {
24+
await del(value.id);
25+
if (deleted) {
26+
deleted(value);
27+
}
28+
}
29+
};
30+
1631
return (
17-
<Link href={`${router.asPath}/${value.id}`}>
18-
<a className="card w-80 bg-base-100 shadow-xl cursor-pointer hover:bg-gray-50">
19-
<figure>
20-
<Image
21-
src={`https://picsum.photos/300/200?r=${customAlphabet(
22-
'0123456789'
23-
)(4)}`}
24-
width={320}
25-
height={200}
26-
alt="Cover"
27-
/>
28-
</figure>
29-
<div className="card-body">
30-
<h2 className="card-title line-clamp-1">
31-
{value.title || 'Missing Title'}
32-
</h2>
33-
<div className="card-actions justify-end">
32+
<div className="card w-80 bg-base-100 shadow-xl cursor-pointer hover:bg-gray-50">
33+
<Link href={`${router.asPath}/${value.id}`}>
34+
<a>
35+
<figure>
36+
<Image
37+
src={`https://picsum.photos/300/200?r=${customAlphabet(
38+
'0123456789'
39+
)(4)}`}
40+
width={320}
41+
height={200}
42+
alt="Cover"
43+
/>
44+
</figure>
45+
</a>
46+
</Link>
47+
<div className="card-body">
48+
<Link href={`${router.asPath}/${value.id}`}>
49+
<a>
50+
<h2 className="card-title line-clamp-1">
51+
{value.title || 'Missing Title'}
52+
</h2>
53+
</a>
54+
</Link>
55+
<div className="card-actions flex w-full justify-between">
56+
<div>
57+
<TimeInfo value={value} />
58+
</div>
59+
<div className="flex space-x-2">
3460
<Avatar user={value.owner} size={18} />
3561
{value.private && (
3662
<div className="tooltip" data-tip="Private">
3763
<LockClosedIcon className="w-4 h-4 text-gray-500" />
3864
</div>
3965
)}
66+
<TrashIcon
67+
className="w-4 h-4 text-gray-500 cursor-pointer"
68+
onClick={() => {
69+
deleteList();
70+
}}
71+
/>
4072
</div>
4173
</div>
42-
</a>
43-
</Link>
74+
</div>
75+
</div>
4476
);
4577
}

samples/todo/pages/index.tsx

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,30 @@
11
import type { NextPage } from 'next';
2-
import { useSession, signIn } from 'next-auth/react';
32
import Spaces from 'components/Spaces';
43
import Link from 'next/link';
4+
import { useCurrentUser } from '@lib/context';
55

66
const Home: NextPage = () => {
7-
const { data: session, status: sessionStatus } = useSession();
8-
9-
if (sessionStatus === 'unauthenticated') {
10-
// kick back to signin
11-
signIn();
12-
}
13-
14-
if (!session) {
15-
return <div>Loading ...</div>;
16-
}
17-
7+
const user = useCurrentUser();
188
return (
199
<>
20-
<div className="mt-8 text-center flex flex-col items-center w-full">
21-
<h1 className="text-2xl text-gray-800">
22-
Welcome {session.user.name || session.user.email}!
23-
</h1>
24-
<div className="w-full p-8">
25-
<h2 className="text-lg md:text-xl text-left mb-8 text-gray-700">
26-
Choose a space to start, or{' '}
27-
<Link href="/create-space">
28-
<a className="link link-primary">
29-
create a new one.
30-
</a>
31-
</Link>
32-
</h2>
33-
<Spaces />
10+
{user && (
11+
<div className="mt-8 text-center flex flex-col items-center w-full">
12+
<h1 className="text-2xl text-gray-800">
13+
Welcome {user.name || user.email}!
14+
</h1>
15+
<div className="w-full p-8">
16+
<h2 className="text-lg md:text-xl text-left mb-8 text-gray-700">
17+
Choose a space to start, or{' '}
18+
<Link href="/create-space">
19+
<a className="link link-primary">
20+
create a new one.
21+
</a>
22+
</Link>
23+
</h2>
24+
<Spaces />
25+
</div>
3426
</div>
35-
</div>
27+
)}
3628
</>
3729
);
3830
};

samples/todo/pages/space/[slug]/[listId]/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export default function TodoList() {
6868
<PlusIcon className="w-6 h-6 text-gray-500" />
6969
</button>
7070
</div>
71-
<ul className="flex flex-col space-y-4 py-8">
71+
<ul className="flex flex-col space-y-4 py-8 w-11/12 md:w-auto">
7272
{todos?.map((todo) => (
7373
<TodoComponent
7474
key={todo.id}

samples/todo/pages/space/[slug]/index.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ function CreateDialog() {
7474
required
7575
placeholder="Title of your list"
7676
className="input input-bordered w-full max-w-xs mt-2"
77+
value={title}
7778
onChange={(
7879
e: FormEvent<HTMLInputElement>
7980
) => setTitle(e.currentTarget.value)}
@@ -120,7 +121,7 @@ export default function SpaceHome() {
120121
const space = useContext(SpaceContext);
121122
const { find } = useList();
122123

123-
const lists = find({
124+
const { data: lists, mutate: invalidateLists } = find({
124125
where: {
125126
space: {
126127
id: space?.id,
@@ -151,9 +152,12 @@ export default function SpaceHome() {
151152
</div>
152153

153154
<ul className="flex flex-wrap gap-6">
154-
{lists.data?.map((list) => (
155+
{lists?.map((list) => (
155156
<li key={list.id}>
156-
<TodoList value={list} />
157+
<TodoList
158+
value={list}
159+
deleted={() => invalidateLists()}
160+
/>
157161
</li>
158162
))}
159163
</ul>

0 commit comments

Comments
 (0)