<!--
One board, at its own address: `/b/<owner>/<number>`, and `?card=<item>`
for a card opened on it — so a board or a card can be linked to, and a note
can say "this card" and mean it.
-->
<script lang="ts">
import { onMount, untrack } from "svelte";
import { boards } from "../../stores/boards.svelte.js";
import { peers } from "../../stores/peers.svelte.js";
import { router } from "../../stores/router.svelte.js";
import ProjectBoard from "../projects/ProjectBoard.svelte";
interface Props {
owner: string;
number: number;
}
let { owner, number }: Props = $props();
onMount(() => {
void peers.load();
return boards.watch();
});
/**
* Whether the card the address names has been opened on the address's
* board. Until it has, the address is what says which card to open, not
* something to overwrite with the card held from before.
*/
let applied = $state(false);
/** Whether the address names this board: only then does its `?card=` belong to it. */
function addressed(): boolean {
const place = router.place;
return place.level === "board" && place.owner === owner && place.number === number;
}
// The board the address names is the trigger; what opening it reads is not.
$effect(() => {
const [who, which] = [owner, number];
untrack(() => {
applied = false;
void boards.open(who, which).then((found) => {
if (found) boards.openItemId = addressed() ? (router.params["card"] ?? null) : null;
applied = true;
});
});
});
// The open card is the address's, so a reload or a shared link opens it.
$effect(() => {
const card = boards.openItemId;
if (!applied) return;
untrack(() => {
if (!addressed() || (router.params["card"] ?? null) === card) return;
const { card: _previous, ...rest } = router.params;
router.replaceParams(card ? { ...rest, card } : rest);
});
});
</script>
<div class="board-level">
<ProjectBoard />
</div>
<style>
.board-level {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
}
</style>