Skip to content
This repository was archived by the owner on Dec 24, 2024. It is now read-only.

Commit db8187a

Browse files
authored
feat: トップページを準備 (#4)
1 parent 6f14770 commit db8187a

File tree

6 files changed

+142
-56
lines changed

6 files changed

+142
-56
lines changed

Diff for: src/components/pages/top/body.tsx

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { type ReactElement } from 'react';
2+
import { type User } from '@/types/user';
3+
4+
interface Props {
5+
user: User<false>;
6+
}
7+
8+
const TopBody = (props: Props): ReactElement => {
9+
const { user } = props;
10+
11+
return (
12+
<div key={user.id}>
13+
<p>
14+
{user.lastName} {user.firstName}
15+
</p>
16+
</div>
17+
);
18+
};
19+
20+
export default TopBody;

Diff for: src/components/pages/top/index.tsx

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { useAtomValue } from 'jotai';
2+
import { type ReactElement } from 'react';
3+
import TopBody from './body';
4+
import { userAtomLoadable } from '@/stores/usersAtom';
5+
6+
const TopPage = (): ReactElement => {
7+
const users = useAtomValue(userAtomLoadable);
8+
9+
return (
10+
<main>
11+
{users.state === 'hasError' && <p>エラー</p>}
12+
{users.state === 'loading' && <p>ローディング中</p>}
13+
{users.state === 'hasData' && users.data.map((user) => <TopBody key={user.id} user={user} />)}
14+
</main>
15+
);
16+
};
17+
18+
export default TopPage;

Diff for: src/pages/index.tsx

+3-52
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,6 @@
1-
import { PlusOutlined, ReloadOutlined } from '@ant-design/icons';
2-
import { Button, Flex } from 'antd';
3-
import { useAtom } from 'jotai';
41
import { type ReactElement } from 'react';
5-
import styled from 'styled-components';
6-
import { countAtom } from '@/stores/counter';
2+
import TopPage from '@/components/pages/top';
73

8-
const Container = styled.div`
9-
height: 100%;
10-
width: 100%;
11-
display: grid;
12-
place-items: center;
13-
place-content: center;
14-
`;
4+
const Page = (): ReactElement => <TopPage />;
155

16-
const Title = styled.p`
17-
font-size: 2rem;
18-
font-weight: bold;
19-
text-align: center;
20-
padding: 1rem;
21-
`;
22-
23-
const IndexPage = (): ReactElement => {
24-
const [count, setCount] = useAtom(countAtom);
25-
26-
return (
27-
<Container>
28-
<Flex align="center" gap="1rem" vertical>
29-
<Title>Hello Vite + React SWC + React Router + styled-components + jotai + Antd!</Title>
30-
<p>Count: {count}</p>
31-
<Flex gap="0.5rem">
32-
<Button
33-
icon={<ReloadOutlined />}
34-
onClick={() => {
35-
setCount(0);
36-
}}
37-
>
38-
Reset
39-
</Button>
40-
<Button
41-
icon={<PlusOutlined />}
42-
onClick={() => {
43-
setCount((_prev) => _prev + 1);
44-
}}
45-
type="primary"
46-
>
47-
Increment
48-
</Button>
49-
</Flex>
50-
</Flex>
51-
</Container>
52-
);
53-
};
54-
55-
export default IndexPage;
6+
export default Page;

Diff for: src/stores/counter.ts

-4
This file was deleted.

Diff for: src/stores/usersAtom.ts

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { atom } from 'jotai';
2+
import { loadable } from 'jotai/utils';
3+
import { type User } from '@/types/user';
4+
import { waitMs } from '@/utils/promise';
5+
6+
const fetchUsers = async (): Promise<Array<User<false>>> => {
7+
await waitMs(2000);
8+
9+
const users: Array<User<false>> = [
10+
{
11+
id: '',
12+
firstName: 'さとる',
13+
lastName: '佐藤',
14+
firstNameKana: '',
15+
lastNameKana: '',
16+
skills: ['JavaScript', 'TypeScript', 'React'],
17+
graduationYear: 2027,
18+
slackName: '',
19+
iconUrl: '',
20+
type: 'active',
21+
grade: 'B1',
22+
position: '部員',
23+
studentNumber: 'k23075',
24+
},
25+
{
26+
id: '',
27+
firstName: '邪馬',
28+
lastName: '山田',
29+
firstNameKana: '',
30+
lastNameKana: '',
31+
skills: ['JavaScript', 'TypeScript', 'React'],
32+
graduationYear: 2027,
33+
slackName: '',
34+
iconUrl: '',
35+
type: 'active',
36+
grade: 'B1',
37+
position: '部員',
38+
studentNumber: 'k23075',
39+
},
40+
];
41+
42+
return users;
43+
};
44+
45+
const usersAtom = atom(async () => await fetchUsers());
46+
export const userAtomLoadable = loadable(usersAtom);

Diff for: src/types/user.ts

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// 現役部員
2+
export interface ActiveUserProps {
3+
type: 'active';
4+
studentNumber: string;
5+
position: string;
6+
grade: string;
7+
}
8+
9+
// OB・OG
10+
export interface OBOGMemberProps {
11+
type: 'obog';
12+
oldPosition: string;
13+
oldStudentNumber: string;
14+
employment: string;
15+
}
16+
17+
// 外部
18+
export interface ExternalMember {
19+
type: 'external';
20+
school: string;
21+
organization: string;
22+
}
23+
24+
// 住所
25+
export interface Address {
26+
postalCode: string;
27+
address: string;
28+
}
29+
30+
// 非公開情報
31+
export interface PrivateProps {
32+
birthdate: string;
33+
gender: string;
34+
phoneNumber: string;
35+
email: string;
36+
currentAddress: Address;
37+
homeAddress: Address;
38+
}
39+
40+
// ユーザー
41+
export interface UserBase {
42+
id: string;
43+
firstName: string;
44+
lastName: string;
45+
firstNameKana: string;
46+
lastNameKana: string;
47+
skills: string[];
48+
graduationYear: number;
49+
slackName: string;
50+
iconUrl: string;
51+
}
52+
53+
export type User<WithPrivate extends boolean> = UserBase &
54+
(ActiveUserProps | OBOGMemberProps | ExternalMember) &
55+
(WithPrivate extends true ? PrivateProps : Record<never, never>);

0 commit comments

Comments
 (0)