Files
everyone-can-use-english/enjoy/src/renderer/components/posts/posts.tsx
an-lee 0644c3bbd7 Feat: make notes on caption (#544)
* add segment model

* add note model

* db handle segment & note

* add notes & segments handler

* refactor media caption components

* segment & note create

* fix type

* update note column & may sync

* display selected words for note

* refactor selected words

* auto select words when editing note

* refactor

* refactor caption component

* display notes

* refactor notes components

* fix

* refactor segment & notes into context

* destroy note

* update locale

* fix caption switch issue

* fix layout

* refactor caption layout

* remove deprecated code

* may share note

* improve UI

* fix notes list auto update after created

* remove console.log

* add notes page

* refactor note parameters

* refactor components

* mark note on transcription

* handle no notes

* improve style

* improve style

* show context menu on selection text

* fix utils
2024-04-26 15:05:36 +08:00

156 lines
4.1 KiB
TypeScript

import { useContext, useEffect, useState } from "react";
import { AppSettingsProviderContext } from "@renderer/context";
import { PostCard, LoaderSpin } from "@renderer/components";
import {
toast,
Button,
Select,
SelectTrigger,
SelectValue,
SelectContent,
SelectItem,
Separator,
} from "@renderer/components//ui";
import { t } from "i18next";
export const Posts = (props: { userId?: string }) => {
const { userId } = props;
const { webApi } = useContext(AppSettingsProviderContext);
const [loading, setLoading] = useState<boolean>(true);
const [type, setType] = useState<
"all" | "recording" | "medium" | "story" | "prompt" | "gpt" | "note"
>("all");
const [by, setBy] = useState<"all" | "following">("following");
const [posts, setPosts] = useState<PostType[]>([]);
const [nextPage, setNextPage] = useState(1);
const handleDelete = (id: string) => {
webApi
.deletePost(id)
.then(() => {
toast.success(t("removeSharingSuccessfully"));
setPosts(posts.filter((post) => post.id !== id));
})
.catch((error) => {
toast.error(t("removeSharingFailed"), { description: error.message });
});
};
const fetchPosts = async (page: number = nextPage) => {
if (!page) return;
webApi
.posts({
page,
items: 10,
userId,
by,
type,
})
.then((res) => {
if (page === 1) {
setPosts(res.posts);
} else {
setPosts([...posts, ...res.posts]);
}
setNextPage(res.next);
})
.catch((err) => {
toast.error(err.message);
})
.finally(() => {
setLoading(false);
});
};
useEffect(() => {
fetchPosts(1);
}, [type, by]);
if (loading) {
return <LoaderSpin />;
}
return (
<div className="max-w-screen-sm mx-auto">
<div className="flex justify-end space-x-4 py-4">
{!userId && (
<Select
value={by}
onValueChange={(value: "all" | "following") => setBy(value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem key="following" value="following">
{t("following")}
</SelectItem>
<SelectItem key="all" value="all">
{t("allUsers")}
</SelectItem>
</SelectContent>
</Select>
)}
<Select
value={type}
onValueChange={(
value: "all" | "recording" | "medium" | "story" | "prompt" | "gpt"
) => setType(value)}
>
<SelectTrigger>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem key="all" value="all">
{t("allTypes")}
</SelectItem>
<SelectItem key="recording" value="recording">
{t("recordingType")}
</SelectItem>
<SelectItem key="note" value="note">
{t("noteType")}
</SelectItem>
<SelectItem key="prompt" value="prompt">
{t("promptType")}
</SelectItem>
<SelectItem key="gpt" value="gpt">
{t("gptType")}
</SelectItem>
<SelectItem key="medium" value="medium">
{t("mediumType")}
</SelectItem>
<SelectItem key="story" value="story">
{t("storyType")}
</SelectItem>
</SelectContent>
</Select>
</div>
{posts.length === 0 && (
<div className="text-center text-muted-foreground py-4">
{t("noOneSharedYet")}
</div>
)}
<div className="space-y-6">
{posts.map((post) => (
<div key={post.id}>
<PostCard post={post} handleDelete={handleDelete} />
<Separator />
</div>
))}
</div>
{nextPage && (
<div className="py-4 flex justify-center">
<Button variant="link" onClick={() => fetchPosts(nextPage)}>
{t("loadMore")}
</Button>
</div>
)}
</div>
);
};