< Summary

Information
Class: items-list.tsx
Assembly: app.features.items
File(s): /home/runner/work/ClutterStock/ClutterStock/frontend/app/features/items/items-list.tsx
Tag: 58_25416222083
Line coverage
75%
Covered lines: 6
Uncovered lines: 2
Coverable lines: 8
Total lines: 80
Line coverage: 75%
Branch coverage
50%
Covered branches: 2
Total branches: 4
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/ClutterStock/ClutterStock/frontend/app/features/items/items-list.tsx

#LineLine coverage
 1import { Form, Link } from "react-router";
 2import { routes } from "~/constants/routes";
 3import type { ItemResponse } from "~/api/client";
 4import { ItemThumb } from "~/components/item-thumb";
 5import { CategoryTag } from "~/components/category-tag";
 6
 7type ItemsListProps = {
 8  locationId: number;
 9  roomId: number;
 10  roomName: string;
 11  items: ItemResponse[];
 12};
 13
 314export function ItemsList({ locationId, roomId, roomName, items }: ItemsListProps) {
 315  if (items.length === 0) {
 116    return (
 17      <div className="card-empty">
 18        <p className="text-muted">No items in {roomName} yet.</p>
 19        <Link to={routes.locations.roomItemsNew(locationId, roomId)} className="link-text" style={{ display: "inline-blo
 20          Add the first item →
 21        </Link>
 22      </div>
 23    );
 24  }
 25
 226  return (
 27    <table className="console-table">
 28      <thead>
 29        <tr>
 30          <th>Item</th>
 31          <th>Category</th>
 32          <th>Notes</th>
 33          <th style={{ width: 1, whiteSpace: "nowrap" }}></th>
 34        </tr>
 35      </thead>
 36      <tbody>
 237        {items.map((item) => (
 238          <tr key={item.id}>
 39            <td>
 40              <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
 41                <ItemThumb name={item.name ?? ""} />
 42                <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
 43                  <span style={{ fontWeight: 500 }}>{item.name ?? "Unnamed"}</span>
 44                  {item.description && (
 45                    <span style={{ fontSize: 11, color: "var(--c-fg-3)" }}>{item.description}</span>
 46                  )}
 47                </div>
 48              </div>
 49            </td>
 50            <td>
 51              {item.category ? <CategoryTag name={item.category} /> : <span style={{ color: "var(--c-fg-3)" }}>—</span>}
 52            </td>
 53            <td style={{ color: "var(--c-fg-3)", fontSize: 12 }}>
 54              {item.notes || "—"}
 55            </td>
 56            <td>
 57              <div style={{ display: "flex", alignItems: "center", gap: 6 }}>
 58                <Link to={routes.locations.itemEdit(locationId, roomId, item.id!)} className="link-chip">
 59                  Edit
 60                </Link>
 61                <Form
 62                  method="post"
 063                  onSubmit={(e) => {
 064                    if (!confirm("Delete this item?")) e.preventDefault();
 65                  }}
 66                >
 67                  <input type="hidden" name="_action" value="delete" />
 68                  <input type="hidden" name="id" value={item.id} />
 69                  <button type="submit" className="link-chip" style={{ color: "var(--c-danger)", borderColor: "transpare
 70                    Delete
 71                  </button>
 72                </Form>
 73              </div>
 74            </td>
 75          </tr>
 76        ))}
 77      </tbody>
 78    </table>
 79  );
 80}