diff --git a/packages/frontend/src/hooks/useBreakpoint.ts b/packages/frontend/src/hooks/useBreakpoint.ts new file mode 100644 index 0000000..ff04951 --- /dev/null +++ b/packages/frontend/src/hooks/useBreakpoint.ts @@ -0,0 +1,14 @@ +import { useSyncExternalStore } from "react"; + +const query = window.matchMedia("@media (width >= 48rem)"); + +const subscribe = (callback: () => void) => { + query.addEventListener("change", callback); + return () => { + query.removeEventListener("change", callback); + }; +} + +const getSnapshot = () => query.matches; + +export const useBreakpoint = () => useSyncExternalStore(subscribe, getSnapshot); diff --git a/packages/frontend/src/routes/Pieces.tsx b/packages/frontend/src/routes/Pieces.tsx index ace6c98..1cb199f 100644 --- a/packages/frontend/src/routes/Pieces.tsx +++ b/packages/frontend/src/routes/Pieces.tsx @@ -5,6 +5,7 @@ import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogT import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; +import { useBreakpoint } from "@/hooks/useBreakpoint"; import { useCache } from "@/hooks/useCache"; import { useLoading } from "@/hooks/useLoading"; import { authors, created, DEBOUNCE, modified, SAVE_DELAY } from "@/snippets"; @@ -25,6 +26,8 @@ export function Pieces() { const [importDialogOpen, setImportDialogOpen] = useState(false); const debounce = useRef(Effect.void); + const breakpoint = useBreakpoint(); + const columns = breakpoint ? 4 : 1; const { isLoading, error, data: pieceIds, refresh } = useLoading(Effect.gen(function* () { yield* debounce.current; @@ -39,7 +42,7 @@ export function Pieces() { return (
-
+
- - - Tytuł - Twórcy - Dodano - Zmodyfikowano - - + {breakpoint && ( + + + Tytuł + Twórcy + Dodano + Zmodyfikowano + + + )} {isLoading ? ( - +
Ładowanie… @@ -98,7 +103,7 @@ export function Pieces() { ) : error !== null ? ( - + {Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${JSON.stringify(error)}`} @@ -121,10 +126,13 @@ function PieceRow(props: PieceRow.Props) { const { isLoading, error, data: piece } = useCache(pieceCache, props.pieceId); + const breakpoint = useBreakpoint(); + const columns = breakpoint ? 4 : 1; + if (isLoading) { return ( - Ładowanie… + Ładowanie… ); } @@ -132,7 +140,7 @@ function PieceRow(props: PieceRow.Props) { if (error !== null) { return ( - + Wystąpił błąd: {Match.value(error).pipe( Match.tag("FetchError", () => "Nie można połączyć się z serwerem"), Match.tag("NotFound", () => "Utwór nie istnieje"), @@ -147,18 +155,25 @@ function PieceRow(props: PieceRow.Props) { return ( - - {piece.name} - - - {authors(piece)} - - - {created(piece)} - - - {modified(piece)} - + {breakpoint ? (<> + + {piece.name} + + + {authors(piece)} + + + {created(piece)} + + + {modified(piece)} + + ) : ( + + {piece.name} +
{authors(piece)}
+
+ )}
); } diff --git a/packages/frontend/src/routes/Repertoires.tsx b/packages/frontend/src/routes/Repertoires.tsx index 7f17a90..79411f9 100644 --- a/packages/frontend/src/routes/Repertoires.tsx +++ b/packages/frontend/src/routes/Repertoires.tsx @@ -5,6 +5,7 @@ import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogT import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; +import { useBreakpoint } from "@/hooks/useBreakpoint"; import { useCache } from "@/hooks/useCache"; import { useLoading } from "@/hooks/useLoading"; import { created, DEBOUNCE, modified } from "@/snippets"; @@ -19,6 +20,8 @@ export function Repertoires() { const [name, setName] = useState(""); const debounce = useRef(Effect.void); + const breakpoint = useBreakpoint(); + const columns = breakpoint ? 4 : 1; const { isLoading, error, data: repertoireIds } = useLoading(Effect.gen(function* () { yield* debounce.current; @@ -32,7 +35,7 @@ export function Repertoires() { return (
-
+
- - - Nazwa - Utwory - Dodano - Zmodyfikowano - - + {breakpoint && ( + + + Nazwa + Utwory + Dodano + Zmodyfikowano + + + )} {isLoading ? ( - +
Ładowanie… @@ -73,7 +78,7 @@ export function Repertoires() { ) : error !== null ? ( - + {Cause.isUnknownException(error) ? "Wystąpił nieznany błąd" : `Wystąpił błąd: ${JSON.stringify(error)}`} @@ -96,10 +101,13 @@ function RepertoireRow(props: RepertoireRow.Props) { const { isLoading, error, data: repertoire } = useCache(repertoireCache, props.repertoireId); + const breakpoint = useBreakpoint(); + const columns = breakpoint ? 4 : 1; + if (isLoading) { return ( - Ładowanie… + Ładowanie… ); } @@ -107,7 +115,7 @@ function RepertoireRow(props: RepertoireRow.Props) { if (error !== null) { return ( - + Wystąpił błąd: {Match.value(error).pipe( Match.tag("FetchError", () => "Nie można połączyć się z serwerem"), Match.tag("NotFound", () => "Repertuar nie istnieje"), @@ -136,18 +144,25 @@ function RepertoireRow(props: RepertoireRow.Props) { return ( - - {repertoire.name} - - - {...piecesParts} - - - {created(repertoire)} - - - {modified(repertoire)} - + {breakpoint ? (<> + + {repertoire.name} + + + {...piecesParts} + + + {created(repertoire)} + + + {modified(repertoire)} + + ) : ( + + {repertoire.name} +
{...piecesParts}
+
+ )}
); }