mirror of
https://github.com/usatiuk/y.git
synced 2025-10-28 10:37:47 +01:00
deleting posts
This commit is contained in:
@@ -11,9 +11,31 @@
|
||||
word-wrap: anywhere;
|
||||
}
|
||||
|
||||
.createdDate {
|
||||
.footer {
|
||||
margin-top: 0.3rem;
|
||||
font-size: 0.7rem;
|
||||
color: #A0A0A0;
|
||||
|
||||
display: flex;
|
||||
flex: auto;
|
||||
width: 100%;
|
||||
|
||||
.info {
|
||||
flex-grow: 1;
|
||||
align-self: start;
|
||||
}
|
||||
|
||||
.actions {
|
||||
align-self: end;
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,43 @@
|
||||
import "./Post.scss";
|
||||
import { Form } from "react-router-dom";
|
||||
|
||||
export function Post({
|
||||
text,
|
||||
createdDate,
|
||||
actions,
|
||||
id,
|
||||
}: {
|
||||
text: string;
|
||||
createdDate: string;
|
||||
actions: boolean;
|
||||
id: number;
|
||||
}) {
|
||||
return (
|
||||
<div className={"post"}>
|
||||
<span className={"text"}>{text}</span>
|
||||
<span className={"createdDate"}>{createdDate}</span>
|
||||
<div className={"footer"}>
|
||||
<div className={"info"}>
|
||||
<span className={"createdDate"}>{createdDate}</span>
|
||||
</div>
|
||||
{actions && (
|
||||
<div className={"actions"}>
|
||||
<Form method={"delete"}>
|
||||
<input
|
||||
hidden={true}
|
||||
name={"postToDeleteId"}
|
||||
value={id}
|
||||
/>
|
||||
<button
|
||||
name="intent"
|
||||
value="deletePost"
|
||||
type={"submit"}
|
||||
>
|
||||
delete
|
||||
</button>
|
||||
</Form>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ export interface IProfileProps {
|
||||
self: boolean;
|
||||
}
|
||||
|
||||
export function Profile(props: IProfileProps) {
|
||||
export function Profile({ self }: IProfileProps) {
|
||||
const loaderData = useLoaderData() as LoaderToType<
|
||||
typeof profileSelfLoader
|
||||
>;
|
||||
@@ -31,7 +31,9 @@ export function Profile(props: IProfileProps) {
|
||||
<div className={"newPost"}>
|
||||
<Form method="post">
|
||||
<textarea placeholder={"Write something!"} name="text" />
|
||||
<button type="submit">Post</button>
|
||||
<button name="intent" value="post" type="submit">
|
||||
Post
|
||||
</button>
|
||||
</Form>
|
||||
</div>
|
||||
<div className={"posts"}>
|
||||
@@ -43,6 +45,8 @@ export function Profile(props: IProfileProps) {
|
||||
text={p.text}
|
||||
createdDate={`${date.toUTCString()}`}
|
||||
key={p.id}
|
||||
id={p.id}
|
||||
actions={self}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { ActionFunctionArgs, redirect } from "react-router-dom";
|
||||
import { login } from "./api/Token";
|
||||
import { isError } from "./api/dto";
|
||||
import { setToken } from "./api/utils";
|
||||
import { post } from "./api/Post";
|
||||
import { createPost, deletePost } from "./api/Post";
|
||||
|
||||
export type ActionToType<T extends (...args: any) => any> =
|
||||
| Exclude<Awaited<ReturnType<T>>, Response>
|
||||
@@ -52,5 +52,12 @@ export async function signupAction({ request }: ActionFunctionArgs) {
|
||||
|
||||
export async function profileSelfAction({ request }: ActionFunctionArgs) {
|
||||
const formData = await request.formData();
|
||||
return await post(formData.get("text")!.toString());
|
||||
const intent = formData.get("intent")!.toString();
|
||||
if (intent == "post") {
|
||||
return await createPost(formData.get("text")!.toString());
|
||||
} else if (intent == "deletePost") {
|
||||
return await deletePost(
|
||||
parseInt(formData.get("postToDeleteId")!.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,21 @@
|
||||
import { PostToArrResp, PostToResp, TPostToArrResp, TPostToResp } from "./dto";
|
||||
import {
|
||||
NoContentToResp,
|
||||
PostToArrResp,
|
||||
PostToResp,
|
||||
TNoContentToResp,
|
||||
TPostToArrResp,
|
||||
TPostToResp,
|
||||
} from "./dto";
|
||||
import { fetchJSONAuth } from "./utils";
|
||||
|
||||
export async function post(text: string): Promise<TPostToResp> {
|
||||
export async function createPost(text: string): Promise<TPostToResp> {
|
||||
return fetchJSONAuth("/post", "POST", PostToResp, {
|
||||
text,
|
||||
});
|
||||
}
|
||||
export async function deletePost(id: number): Promise<TNoContentToResp> {
|
||||
return fetchJSONAuth(`/post/${id.toString()}`, "DELETE", NoContentToResp);
|
||||
}
|
||||
|
||||
export async function getPosts(author: string): Promise<TPostToArrResp> {
|
||||
return fetchJSONAuth(`/post?author=${author}`, "GET", PostToArrResp);
|
||||
|
||||
@@ -10,6 +10,12 @@ function CreateAPIResponse<T extends z.ZodTypeAny>(obj: T) {
|
||||
return z.union([ErrorTo, obj]);
|
||||
}
|
||||
|
||||
export const NoContentTo = z.object({});
|
||||
export type TNoContentTo = z.infer<typeof NoContentTo>;
|
||||
|
||||
export const NoContentToResp = CreateAPIResponse(NoContentTo);
|
||||
export type TNoContentToResp = z.infer<typeof NoContentToResp>;
|
||||
|
||||
export const PersonSignupTo = z.object({
|
||||
username: z.string(),
|
||||
fullName: z.string(),
|
||||
|
||||
@@ -47,7 +47,11 @@ export async function fetchJSON<T, P extends { parse: (arg: string) => T }>(
|
||||
headers: reqHeaders(),
|
||||
body: reqBody(),
|
||||
});
|
||||
return parser.parse(await response.json());
|
||||
|
||||
const json = await response.json().catch(() => {
|
||||
return {};
|
||||
});
|
||||
return parser.parse(json);
|
||||
}
|
||||
|
||||
export async function fetchJSONAuth<T, P extends { parse: (arg: string) => T }>(
|
||||
|
||||
Reference in New Issue
Block a user