Greums's picture
major improvements to the app
a417977
raw
history blame
5.3 kB
import {Post as PostType, Topic as TopicType, topicsCtx} from "@/contexts/topics";
import style from "./style.module.scss";
import {Preview} from "../preview";
import {iso8601ToFrench} from "@/utils/dates";
import {FormGroup} from "../form";
import {Slider} from "../slider";
import {Button} from "../button";
import {settingsCtx} from "@/contexts/settings";
import {useContext, useState, useMemo} from "preact/hooks";
import {Wysiwyg} from "@/components/wysiwyg";
import {
ChevronRight,
X,
} from "preact-feather";
import cn from "classnames";
import {Pagination} from "@/components/pagination";
import {Spinner} from "@/components/spinner";
import {logCtx} from "@/contexts/log";
const postsPerPage = 10;
export function Topic(props: {
topic: TopicType,
page: number,
setPage: (newPage: number) => void,
}) {
/**
* TODO
* prendre la générationDate du premier post et remplacer toutes la dates (IA) avec celle-ci en calculant le delta en en l'appliquant à chaque post
* Pour il faut remplacer la date des citations en prenant en compte le delta
*
*/
const [topicsContext, , topicsActions] = useContext(topicsCtx);
const [settings, setSettings] = useContext(settingsCtx);
const [, , logActions] = useContext(logCtx);
const [wysiwygText, setWysiwygText] = useState("");
const addQuote = (post: PostType) => {
setWysiwygText((wysiwygText.length > 1 ? `${wysiwygText}\n\n` : "") + post.content.split("\n").map(l => `> ${l}`).join("\n"))
}
const postsSlice = useMemo(
() => props.topic.posts.slice(props.page * postsPerPage, (props.page + 1) * postsPerPage),
[props.page, props.topic.posts]
);
const pendingGeneration = topicsContext.generation === "pending";
const pagination = (
<Pagination
pageCount={Math.ceil(props.topic.posts.length / postsPerPage)}
page={props.page}
setPage={props.setPage}
/>
);
return (
<div>
<div className={style.wrapper}>
{pagination}
<div className={style.postsContainer}>
{postsSlice.map((post, index) => {
const realIndex = postsPerPage * props.page + index;
return (
<Post
post={post}
quote={() => addQuote(post)}
remove={() => topicsActions.deletePost(props.topic.id, realIndex)}
loading={pendingGeneration && realIndex >= props.topic.posts.length - 1}
/>
)
})}
</div>
{pagination}
</div>
<div>
<h2>Ajout de posts</h2>
<div className={style.generationSettings}>
<FormGroup>
<label htmlFor="postCount">Nombre de posts</label>
<Slider
name="postCount"
value={settings.postCount}
onChange={(v) => setSettings({...settings, postCount: v})}
min={1}
max={10}
step={1}
/>
</FormGroup>
</div>
<Button
onClick={() => topicsActions.generatePosts(settings, logActions.log, props.topic)}
secondary={true}
loading={pendingGeneration}
>
{pendingGeneration ? "Génération en cours…" : "Générer"}
</Button>
</div>
<hr/>
<div>
<Wysiwyg
showTitle={false}
onSubmit={(user, title, text) => {
topicsActions.addPost(props.topic.id, user, text)
}}
text={wysiwygText}
setText={setWysiwygText}
/>
</div>
</div>
)
}
function Post(props: {
post: PostType,
quote: () => void,
remove: () => void,
loading: boolean,
}) {
return (
<div className={style.post}>
<div className={style.postHeader}>
<img src="https://image.jeuxvideo.com/avatar-sm/default.jpg" className={style.avatar} alt="ahi"/>
<div className={style.user}>{props.post.user}</div>
<div className={style.date}>{iso8601ToFrench(props.post.date)}</div>
<div className={style.actions}>
<div className={cn(style.action, style.actionDanger)} title="Supprimer" onClick={props.remove}>
<X size={16} style={{right: 0.6, top: 1.2}}/>
</div>
<div className={style.action} title="Citer" onClick={props.quote}>
<ChevronRight size={16} style={{left: 1.2}}/>
</div>
</div>
</div>
<Preview raw={props.post.content}/>
{props.loading ? <Spinner className={style.spinner}/> : null}
</div>
)
}