< Summary

Information
Class: room-form.tsx
Assembly: app.features.rooms
File(s): /home/runner/work/ClutterStock/ClutterStock/frontend/app/features/rooms/room-form.tsx
Tag: 58_25416222083
Line coverage
0%
Covered lines: 0
Uncovered lines: 9
Coverable lines: 9
Total lines: 99
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 4
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/ClutterStock/ClutterStock/frontend/app/features/rooms/room-form.tsx

#LineLine coverage
 1import { Form, Link } from "react-router";
 2import type { RoomResponse } from "~/api/client";
 3import { fieldError } from "~/lib/forms";
 4
 5type RoomFormProps = {
 6  title: string;
 7  submitLabel: string;
 8  error?: string;
 9  fieldErrors?: Record<string, string[]>;
 10  room?: RoomResponse | null;
 11  locationId: number;
 12  cancelTo: string;
 13};
 14
 015export function RoomForm({
 16  title,
 17  submitLabel,
 18  error,
 19  fieldErrors,
 20  room,
 21  locationId: _locationId,
 22  cancelTo,
 23}: RoomFormProps) {
 024  const nameError = fieldError(fieldErrors, "name");
 025  const descriptionError = fieldError(fieldErrors, "description");
 026  if (room === null) {
 027    return (
 28      <div className="card-padded">
 29        <p className="text-muted">Room not found.</p>
 30        <Link to={cancelTo} className="link-text" style={{ display: "inline-block", marginTop: 8 }}>
 31          Back to rooms
 32        </Link>
 33      </div>
 34    );
 35  }
 36
 037  return (
 38    <div className="card-padded">
 39      <h2 className="card-title">{title}</h2>
 40      <Form method="post" className="form-group">
 41        {error && <p className="text-error">{error}</p>}
 42        <div className="form-field">
 43          <label htmlFor="name" className="form-label">
 44            Name
 45          </label>
 46          <input
 47            id="name"
 48            name="name"
 49            type="text"
 50            required
 51            autoFocus={!room}
 52            defaultValue={room?.name ?? ""}
 53            className="form-input"
 54            placeholder="e.g. Living Room, Garage"
 55            aria-invalid={nameError ? true : undefined}
 56          />
 57          {nameError && <p className="text-error" style={{ marginTop: 4 }}>{nameError}</p>}
 58        </div>
 59        <div className="form-field">
 60          <label htmlFor="description" className="form-label">
 61            Description (optional)
 62          </label>
 63          <textarea
 64            id="description"
 65            name="description"
 66            rows={2}
 67            defaultValue={room?.description ?? ""}
 68            className="form-input"
 69            placeholder="e.g. Main gathering space"
 70            aria-invalid={descriptionError ? true : undefined}
 71          />
 72          {descriptionError && <p className="text-error" style={{ marginTop: 4 }}>{descriptionError}</p>}
 73        </div>
 74        <div className="form-actions">
 75          <button type="submit" className="btn-primary">
 76            {submitLabel}
 77          </button>
 78          <Link to={cancelTo} className="btn-secondary">
 79            Cancel
 80          </Link>
 81        </div>
 82      </Form>
 83      {room?.id != null && (
 84        <Form
 85          method="post"
 86          style={{ marginTop: 24, paddingTop: 16, borderTop: "1px solid var(--c-border)" }}
 087          onSubmit={(e) => {
 088            if (!confirm("Delete this room and all its items?")) {
 089              e.preventDefault();
 90            }
 91          }}
 92        >
 93          <input type="hidden" name="_action" value="delete" />
 94          <button type="submit" className="btn-danger">Delete room</button>
 95        </Form>
 96      )}
 97    </div>
 98  );
 99}

Methods/Properties

RoomForm()V
(anonymous_1)()V