import React, { useEffect, useState } from "react";
import { useParams } from 'react-router-dom';
import authenticatedFetch from "@iqmetrix/authenticated-fetch";
import { PageLayout } from "@iqmetrix/layout";
import { Alert, Button, PageHeader, Form, Input, Select, Skeleton } from "@iqmetrix/antd";
interface Post {
userId: number;
id: number;
title: string;
body: string;
}
interface User {
id: string;
name: string;
}
const getPostUrl = (id: string) => `https://jsonplaceholder.typicode.com/posts/${id}`;
const usersUrl = `https://jsonplaceholder.typicode.com/users`;
const useUsers = () => {
const [isLoading, setIsLoading] = useState<boolean>(true);
const [error, setError] = useState<string | undefined>();
const [users, setUsers] = useState<Array<User> | undefined>();
useEffect(() => {
const doFetch = async () => {
setIsLoading(true);
try {
const res = await authenticatedFetch(usersUrl);
if (!res.ok) throw new Error(res.status.toString());
const results = await res.json() as Array<User>;
setUsers(results)
} catch (error) {
setError(error.toString());
} finally {
setIsLoading(false);
}
};
doFetch();
}, []);
return {
isLoading,
error,
users,
}
};
const usePost = (id: string) => {
const [isLoading, setIsLoading] = useState<boolean>(true);
const [error, setError] = useState<string | undefined>();
const [post, setPost] = useState<Post | undefined>();
const [isSaving, setIsSaving] = useState<boolean>(false);
useEffect(() => {
const doFetch = async () => {
setIsLoading(true);
try {
const res = await authenticatedFetch(getPostUrl(id));
if (!res.ok) throw new Error(res.status.toString());
const result = await res.json() as Post;
setPost(result)
} catch (error) {
setError(error.toString());
} finally {
setIsLoading(false);
}
};
doFetch();
}, [id]);
const savePost = async (post: Post) => {
setIsSaving(true);
try {
const res = await authenticatedFetch(getPostUrl(id), {
method: 'PUT',
body: JSON.stringify(post),
});
if (!res.ok) throw new Error(res.status.toString());
alert(JSON.stringify(post, undefined, 2));
} catch (error) {
setError(error.toString());
} finally {
setIsSaving(false);
}
};
return {
error,
isLoading,
isSaving,
post,
savePost,
}
};
export const PostView = () => {
const { id } = useParams<{ id: string}>();
const {
error: usersError,
isLoading: isUsersLoading,
users,
} = useUsers();
const {
error: postError,
isLoading: isPostLoading,
isSaving,
post,
savePost,
} = usePost(id)
const errors = [postError, usersError].filter(error => !!error);
return (
<PageLayout size="full">
{{
header: <PageHeader title={`Resource ${id}`} />,
messages: errors.map(error => <Alert message={error?.toString()} closable />),
content: [
{
primary: (
<Skeleton loading={isPostLoading} >
<Form
initialValues={post}
layout="vertical"
name="post"
onFinish={savePost}
>
<Form.Item
label="Title"
name="title"
rules={[
{
required: true,
message: "You must enter a title"
}
]}
>
<Input />
</Form.Item>
<Form.Item
label="By"
name="userId"
rules={[
{
required: true,
message: "Your post must have an author"
}
]}
>
<Select loading={isUsersLoading}>
{users && users.map(user => (
<Select.Option value={user.id} title={user.name} key={user.id}>
{user.name}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item label="Body" name="body" >
<Input.TextArea rows={10} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" loading={isSaving} >
Save
</Button>
</Form.Item>
</Form>
</Skeleton>
),
},
],
}}
</PageLayout>
);
};