< Summary

Information
Class: location-form.tsx
Assembly: app.components.locations
File(s): /home/runner/work/ClutterStock/ClutterStock/frontend/app/components/locations/location-form.tsx
Tag: 58_25416222083
Line coverage
0%
Covered lines: 0
Uncovered lines: 9
Coverable lines: 9
Total lines: 95
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/components/locations/location-form.tsx

#LineLine coverage
 1import { Form, Link } from "react-router";
 2import type { LocationResponse } from "~/api/client";
 3import { fieldError } from "~/lib/forms";
 4
 5type LocationFormProps = {
 6  title: string;
 7  submitLabel: string;
 8  error?: string;
 9  fieldErrors?: Record<string, string[]>;
 10  location?: LocationResponse | null;
 11};
 12
 013export function LocationForm({
 14  title,
 15  submitLabel,
 16  error,
 17  fieldErrors,
 18  location,
 19}: LocationFormProps) {
 020  const nameError = fieldError(fieldErrors, "name");
 021  const descriptionError = fieldError(fieldErrors, "description");
 022  if (location === null) {
 023    return (
 24      <div className="card-padded">
 25        <p className="text-muted">Location not found.</p>
 26        <Link to="/locations" className="link-text" style={{ display: "inline-block", marginTop: 8 }}>
 27          Back to locations
 28        </Link>
 29      </div>
 30    );
 31  }
 32
 033  return (
 34    <div className="card-padded">
 35      <h2 className="card-title">{title}</h2>
 36      <Form method="post" className="form-group">
 37        {error && <p className="text-error">{error}</p>}
 38        <div className="form-field">
 39          <label htmlFor="name" className="form-label">
 40            Name
 41          </label>
 42          <input
 43            id="name"
 44            name="name"
 45            type="text"
 46            required
 47            autoFocus={!location}
 48            defaultValue={location?.name ?? ""}
 49            className="form-input"
 50            placeholder="e.g. Home, Office"
 51            aria-invalid={nameError ? true : undefined}
 52          />
 53          {nameError && <p className="text-error" style={{ marginTop: 4 }}>{nameError}</p>}
 54        </div>
 55        <div className="form-field">
 56          <label htmlFor="description" className="form-label">
 57            Description (optional)
 58          </label>
 59          <textarea
 60            id="description"
 61            name="description"
 62            rows={2}
 63            defaultValue={location?.description ?? ""}
 64            className="form-input"
 65            placeholder="e.g. Main residence"
 66            aria-invalid={descriptionError ? true : undefined}
 67          />
 68          {descriptionError && <p className="text-error" style={{ marginTop: 4 }}>{descriptionError}</p>}
 69        </div>
 70        <div className="form-actions">
 71          <button type="submit" className="btn-primary">
 72            {submitLabel}
 73          </button>
 74          <Link to="/locations" className="btn-secondary">
 75            Cancel
 76          </Link>
 77        </div>
 78      </Form>
 79      {location?.id != null && (
 80        <Form
 81          method="post"
 82          style={{ marginTop: 24, paddingTop: 16, borderTop: "1px solid var(--c-border)" }}
 083          onSubmit={(e) => {
 084            if (!confirm("Delete this location and all its rooms and items?")) {
 085              e.preventDefault();
 86            }
 87          }}
 88        >
 89          <input type="hidden" name="_action" value="delete" />
 90          <button type="submit" className="btn-danger">Delete location</button>
 91        </Form>
 92      )}
 93    </div>
 94  );
 95}

Methods/Properties

LocationForm()V
(anonymous_1)()V