posts prettier

This commit is contained in:
Stepan Usatiuk
2023-12-16 20:33:01 +01:00
parent 2aa2160300
commit d98906a23f
11 changed files with 75 additions and 30 deletions

View File

@@ -1,20 +1,14 @@
import "./Auth.scss";
import { Form, Link, useActionData, useNavigation } from "react-router-dom";
import { loginAction } from "./actions";
import { ActionToType, loginAction } from "./actions";
import { isError } from "./api/dto";
export function Login() {
const data = useActionData() as
| Awaited<ReturnType<typeof loginAction>>
| undefined;
if (data && !isError(data)) {
return <div className="authForm">Login success</div>;
}
const data = useActionData() as ActionToType<typeof loginAction>;
let errors: JSX.Element[] = [];
if (data) {
if (isError(data)) {
errors = data.errors.map((e) => {
return <a>{e}</a>;
});

19
client/src/Post.scss Normal file
View File

@@ -0,0 +1,19 @@
.post {
display: flex;
flex-direction: column;
border: 1px solid #E0E0E0;
border-radius: 7px;
padding: 7px;
resize: none;
margin: 1rem 0;
.text {
word-wrap: anywhere;
}
.createdDate {
margin-top: 0.3rem;
font-size: 0.7rem;
color: #A0A0A0;
}
}

16
client/src/Post.tsx Normal file
View File

@@ -0,0 +1,16 @@
import "./Post.scss";
export function Post({
text,
createdDate,
}: {
text: string;
createdDate: string;
}) {
return (
<div className={"post"}>
<span className={"text"}>{text}</span>
<span className={"createdDate"}>{createdDate}</span>
</div>
);
}

View File

@@ -55,6 +55,6 @@
}
.posts {
padding: 2rem;
padding: 0 2rem 2rem;
}
}

View File

@@ -3,6 +3,7 @@ import { Form, Link, useLoaderData } from "react-router-dom";
import { LoaderToType, profileSelfLoader } from "./loaders";
import { isError } from "./api/dto";
import { ProfileCard } from "./ProfileCard";
import { Post } from "./Post";
export interface IProfileProps {
self: boolean;
@@ -16,6 +17,11 @@ export function Profile(props: IProfileProps) {
if (!loaderData || isError(loaderData)) {
return <div>Error</div>;
}
const sortedPosts = loaderData.posts?.sort(
(a, b) => b.createdAt - a.createdAt,
);
return (
<div className={"profileView"}>
<div className={"profileInfo"}>
@@ -29,12 +35,15 @@ export function Profile(props: IProfileProps) {
</Form>
</div>
<div className={"posts"}>
{loaderData.posts &&
loaderData.posts.map((p) => {
{sortedPosts &&
sortedPosts.map((p) => {
const date = new Date(p.createdAt * 1000);
return (
<div key={p.id} className={"post"}>
{p.text}
</div>
<Post
text={p.text}
createdDate={`${date.toUTCString()}`}
key={p.id}
/>
);
})}
</div>

View File

@@ -1,20 +1,14 @@
import "./Auth.scss";
import { Form, Link, useActionData, useNavigation } from "react-router-dom";
import { signupAction } from "./actions";
import { ActionToType, signupAction } from "./actions";
import { isError } from "./api/dto";
export function Signup() {
const data = useActionData() as
| Awaited<ReturnType<typeof signupAction>>
| undefined;
if (data && !isError(data)) {
return <div className="authForm">Signup success</div>;
}
const data = useActionData() as ActionToType<typeof signupAction>;
let errors: JSX.Element[] = [];
if (data) {
if (isError(data)) {
errors = data.errors.map((e) => {
return <a>{e}</a>;
});

View File

@@ -5,6 +5,10 @@ import { isError } from "./api/dto";
import { setToken } from "./api/utils";
import { post } from "./api/Post";
export type ActionToType<T extends (...args: any) => any> =
| Exclude<Awaited<ReturnType<T>>, Response>
| undefined;
export async function loginAction({ request }: ActionFunctionArgs) {
const formData = await request.formData();
const ret = await login(

View File

@@ -45,6 +45,7 @@ export const PostTo = z.object({
id: z.number(),
authorUuid: z.string(),
text: z.string(),
createdAt: z.number(),
});
export type TPostTo = z.infer<typeof PostTo>;