Skip to content

Commit

Permalink
before experimental version
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanflorence committed Oct 20, 2023
1 parent c8894c4 commit d8a6db1
Show file tree
Hide file tree
Showing 11 changed files with 361 additions and 359 deletions.
14 changes: 2 additions & 12 deletions app/routes/board.$id/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ type CardProps =
content: string | null;
id: number;
columnId: number;
renderedColumnId: number;
order: number;
nextOrder: number;
previousOrder: number;
Expand All @@ -28,7 +27,6 @@ type CardProps =
columnId?: number;
nextOrder?: number;
previousOrder?: number;
renderedColumnId?: number;
};

export function Card({
Expand All @@ -40,7 +38,6 @@ export function Card({
order,
nextOrder,
previousOrder,
renderedColumnId,
}: CardProps) {
let ctxt = useContext(UNSAFE_DataRouterContext);
invariant(ctxt);
Expand All @@ -50,11 +47,6 @@ export function Card({
let [acceptDrop, setAcceptDrop] = useState<"none" | "top" | "bottom">(
"none",
);
// let fetcher = useFetcher({ key: `card:${id}` });
let fetcher = useFetcher({
persist: true,
key: `${INTENTS.moveItem}:${id}`,
});

return (
<li
Expand All @@ -74,7 +66,6 @@ export function Card({
}}
onDrop={(event) => {
if (disabled) return;
console.log("DROPPED!");
event.stopPropagation();

let { cardId, columnId: oldColumnId } = JSON.parse(
Expand All @@ -91,15 +82,14 @@ export function Card({
formData.set("intent", INTENTS.moveItem);
formData.set("order", String(newOrder));
formData.set("cardId", String(cardId));
formData.set("newColumnId", String(renderedColumnId));
formData.set("oldColumnId", String(oldColumnId));
formData.set("columnId", String(columnId));

let fetcherKey = `${INTENTS.moveItem}:${cardId}`;
router.fetch(
fetcherKey,
"routes/board.$id",
location.pathname,
{ formMethod: "post", formData, persist: true },
{ formMethod: "post", formData /*persist: true*/ },
);

setAcceptDrop("none");
Expand Down
4 changes: 1 addition & 3 deletions app/routes/board.$id/column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ export function Column({
}}
onDrop={(event) => {
if (disabled) return;
console.log("Column DROP");

let { cardId, columnId: oldColumnId } = JSON.parse(
event.dataTransfer.getData(CONTENT_TYPES.card),
Expand All @@ -85,8 +84,7 @@ export function Column({
formData.set("intent", INTENTS.moveItem);
formData.set("order", "1");
formData.set("cardId", String(cardId));
formData.set("newColumnId", String(columnId));
formData.set("oldColumnId", String(oldColumnId));
formData.set("columnId", String(columnId));

let fetcherKey = `${INTENTS.moveItem}:${cardId}`;
router.fetch(
Expand Down
95 changes: 38 additions & 57 deletions app/routes/board.$id/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,70 +10,52 @@ import invariant from "tiny-invariant";

export { loader, action };

type FetcherWithFormData = ReturnType<typeof useFetchers>[0] & {
formData: FormData;
};

export default function Board() {
let { board } = useLoaderData<typeof loader>();
let fetchers = useFetchers();
console.log(
"fetchers",
fetchers.map((f) => `${f.state}:${f.formData?.get("cardId")}`),
);

console.group();
console.log(
"board\t\t",
board.columns.map((col) => col.items.length).join(" | "),
);
let colMap = new Map(
board.columns.map((col) => [
col.id,
{
...col,
// copy items cause we'll mutate them for optimistic UI
items: [...col.items],
},
]),
);
console.log(
"map\t\t\t",
[...colMap.values()].map((col) => col.items.length).join(" | "),
);

for (let fetcher of fetchers) {
if (fetcher.formData?.get("intent") === INTENTS.moveItem) {
// get the formData going over the network
let newColumnId = Number(fetcher.formData.get("newColumnId"));
let oldColumnId = Number(fetcher.formData.get("oldColumnId"));
let movingFetchers = useFetchers()
.filter((fetcher): fetcher is FetcherWithFormData => {
return fetcher.formData?.get("intent") === INTENTS.moveItem;
})
.reduce((map, fetcher) => {
// TODO: use a json fetcher
let cardId = Number(fetcher.formData.get("cardId"));
let columnId = Number(fetcher.formData.get("columnId"));
let order = Number(fetcher.formData.get("order"));
invariant(newColumnId, "missing newColumnId");
invariant(oldColumnId, "missing newColumnId");
invariant(cardId, "missing cardId");
invariant(order, "missing order");
invariant(cardId, "missing cardId in formData");
invariant(columnId, "missing columnId in formData");
return map.set(Number(cardId), {
columnId: Number(columnId),
order: Number(order),
});
}, new Map<number, { columnId: number; order: number }>());

// get the two columns
let oldCol = colMap.get(oldColumnId);
invariant(oldCol, "missing old column");
let newCol = colMap.get(newColumnId);
invariant(newCol, "missing new column");
type ColumnWithItems = (typeof board.columns)[0] & {
items: typeof board.items;
};

// remove the item from the old column
let actualIndex = oldCol.items.findIndex(
(item) => item.id === cardId,
);
invariant(actualIndex > -1, "missing item in old column");
let [actualItem] = oldCol.items.splice(actualIndex, 1);
// copy the columns so we can add items to them, including optimistic items
let columns = board.columns.reduce(
(map, column) => map.set(column.id, { ...column, items: [] }),
new Map<number, ColumnWithItems>(),
);

// push it to the new one with the new order
newCol.items.push({ ...actualItem, order });
}
// add items to their columns
for (let item of board.items) {
// check optimistic versions first
let movingItem = movingFetchers.get(item.id);
let columnId = movingItem ? movingItem.columnId : item.columnId;
let column = columns.get(columnId);
invariant(column, "missing column");
column.items.push(
movingItem ? { ...item, order: movingItem.order } : item,
);
}

console.log(
"map after\t",
[...colMap.values()].map((col) => col.items.length).join(" | "),
);
console.groupEnd();

let scrollContainerRef = useRef<HTMLDivElement>(null);
function scrollRight() {
invariant(scrollContainerRef.current);
Expand All @@ -90,7 +72,7 @@ export default function Board() {
<h1 className="px-8 my-4 text-2xl font-medium">{board.name}</h1>

<div className="flex flex-grow min-h-0 h-full items-start gap-4 px-8 pb-4">
{[...colMap.values()].map((col) => {
{[...columns.values()].map((col) => {
return (
<Column key={col.id} name={col.name} columnId={col.id}>
{col.items
Expand All @@ -105,8 +87,7 @@ export default function Board() {
// important to pass the item's column ID, because when it's
// optimistic it can be a different column than the one it's
// rendered in
columnId={item.columnId}
renderedColumnId={col.id}
columnId={col.id}
previousOrder={
items[index - 1] ? items[index - 1].order : 0
}
Expand Down
33 changes: 18 additions & 15 deletions app/routes/board.$id/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export async function loader({ request, params }: LoaderFunctionArgs) {
}

export async function action({ request, params }: ActionFunctionArgs) {
let id = Number(params.id);
invariant(id, "Missing board ID");
let boardId = Number(params.id);
invariant(boardId, "Missing boardId");

let data = await request.formData();
let intent = String(data.get("intent"));
Expand All @@ -34,7 +34,7 @@ export async function action({ request, params }: ActionFunctionArgs) {
case INTENTS.createColumn: {
let name = String(data.get("name"));
if (!name) throw badRequest("Missing name");
await createColumn(id, name);
await createColumn(boardId, name);
break;
}
case INTENTS.updateColumn: {
Expand All @@ -50,20 +50,24 @@ export async function action({ request, params }: ActionFunctionArgs) {
let columnId = Number(data.get("columnId"));
if (!title || !columnId)
throw badRequest("Missing title or columnId");
await createItem(columnId, title);
await createItem(boardId, columnId, title);
break;
}
case INTENTS.moveItem: {
let order = Number(data.get("order"));
let cardId = Number(data.get("cardId"));
let columnId = Number(data.get("newColumnId"));
let columnId = Number(data.get("columnId"));
await moveItem(cardId, columnId, order);
break;
}
default: {
throw new Error("Unknown intent");
}
}

return request.headers.get("Sec-Fetch-Dest") === "document"
? redirect(`/board/${id}`)
: { ok: true, id };
? redirect(`/board/${boardId}`)
: { ok: true, boardId };
}

////////////////////////////////////////////////////////////////////////////////
Expand All @@ -86,14 +90,19 @@ async function moveItem(
});
}

export async function createItem(columnId: number, title: string) {
export async function createItem(
boardId: number,
columnId: number,
title: string,
) {
let itemCountForColumn = await prisma.item.count({
where: { columnId },
});
return prisma.item.create({
data: {
title,
columnId,
boardId,
order: itemCountForColumn + 1,
},
});
Expand Down Expand Up @@ -129,14 +138,8 @@ export async function getBoardData(boardId: number) {
id: boardId,
},
include: {
items: true,
columns: {
include: {
items: {
orderBy: {
order: "asc",
},
},
},
orderBy: {
order: "asc",
},
Expand Down
12 changes: 9 additions & 3 deletions app/routes/signup/route.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { json, type ActionFunctionArgs, redirect } from "@remix-run/node";
import {
json,
type ActionFunctionArgs,
redirect,
} from "@remix-run/node";
import { validate } from "./validate";
import { Form, useActionData } from "@remix-run/react";
import { createAccount } from "./create-account";
Expand All @@ -20,7 +24,6 @@ export async function action({ request }: ActionFunctionArgs) {

export default function Signup() {
let actionResult = useActionData<typeof action>();
console.log(actionResult);

return (
<>
Expand Down Expand Up @@ -66,7 +69,10 @@ export default function Signup() {
>
Password{" "}
{actionResult?.errors?.password && (
<span id="password-error" className="text-brand-red">
<span
id="password-error"
className="text-brand-red"
>
{actionResult.errors.password}
</span>
)}
Expand Down
Loading

0 comments on commit d8a6db1

Please sign in to comment.