Deduplicate, don't debounce on first visit

This commit is contained in:
2024-12-29 23:19:55 +01:00
parent bf4361d207
commit c59c0e106b
6 changed files with 131 additions and 65 deletions

View File

@@ -1,4 +1,4 @@
import { pieceCache, User } from "@/cache";
import { pieceCache } from "@/cache";
import { client } from "@/client";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
@@ -6,10 +6,11 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { useLoadingEffect } from "@/hooks/useLoading";
import { authors, created, DEBOUNCE, modified } from "@/snippets";
import { PieceId } from "common";
import { Cause, Clock, Duration, Effect, Option } from "effect";
import { Cause, Effect } from "effect";
import { Loader2, Plus } from "lucide-react";
import { FormEventHandler, ReactNode, useId, useState } from "react";
import { FormEventHandler, useId, useRef, useState } from "react";
import { Link, useNavigate } from "react-router-dom";
export function Pieces() {
@@ -17,8 +18,10 @@ export function Pieces() {
const [name, setName] = useState("");
const [author, setAuthor] = useState("");
const debounce = useRef(Effect.void);
const { isLoading, error, data: pieceIds } = useLoadingEffect(Effect.gen(function* () {
yield* Clock.sleep(Duration.millis(500));
yield* debounce.current;
const { error, data } = yield* Effect.promise((signal) => client.piece.get({
query: {
...(name !== "" ? { name } : undefined),
@@ -50,14 +53,20 @@ export function Pieces() {
type="text"
placeholder="Tytuł"
value={name}
onChange={(e) => setName(e.target.value)}
onChange={(e) => {
setName(e.target.value);
debounce.current = DEBOUNCE;
}}
/>
<Input
className="w-[32ch]"
type="text"
placeholder="Twórcy"
value={author}
onChange={(e) => setAuthor(e.target.value)}
onChange={(e) => {
setAuthor(e.target.value);
debounce.current = DEBOUNCE;
}}
/>
</div>
<Table>
@@ -120,30 +129,19 @@ function PieceRow(props: PieceRow.Props) {
);
}
const composerParts: ReactNode[] = [];
if (Option.isSome(piece.composer)) composerParts.push(piece.composer.value);
if (Option.isSome(piece.arranger)) composerParts.push(`opracowanie: ${piece.arranger.value}`);
if (Option.isSome(piece.lyricist)) composerParts.push(`słowa: ${piece.lyricist.value}`);
if (composerParts.length === 0) composerParts.push(<em>Nieznani</em>);
return (
<TableRow>
<TableCell>
<Link className="underline" to={piece.pieceId}>{piece.name}</Link>
</TableCell>
<TableCell>
{...composerParts.flatMap((x, i, a) => i < a.length - 1 ? [x, <br />] : [x])}
{authors(piece)}
</TableCell>
<TableCell className="text-center text-xs">
{piece.createdAt}
{Option.isSome(piece.createdBy) && <><br />przez {piece.createdBy.value.username}</>}
{created(piece)}
</TableCell>
<TableCell className="text-center text-xs">
{Option.isNone(piece.modifiedAt) && Option.isNone(piece.modifiedBy) ? "\u2014"
: Option.isSome(piece.modifiedAt) && Option.isNone(piece.modifiedBy) ? piece.modifiedAt.value
: Option.isNone(piece.modifiedAt) ? `przez ${(piece.modifiedBy as Option.Some<User>).value.username}`
: <>{piece.modifiedAt.value}<br />przez {(piece.modifiedBy as Option.Some<User>).value.username}</>}
{modified(piece)}
</TableCell>
</TableRow>
);