jhoang304 / jhoang304/Whelp

Extract a shared RestaurantForm so the create and edit modals cannot drift

Open
#61 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
TypeScript
Stars
0
Forks
0
Avg merge
2h 19m
Merged PRs (30d)
30

Description

Follow-up to #22, which suggested this and which I closed having done only half
of it. Worth its own issue rather than being lost in a closed one.

## Background

#22 was largely a story about the two restaurant forms drifting apart. The edit
modal had grown a `/\.com$/` website rule the create modal never had, which
locked owners of `runchickenrun.com/las-vegas/` (and every `.org`, `.net`,
`.co`) out of editing *any* field. While fixing it I extracted the field rules
into `react-app/src/utils/restaurantValidation.ts` and pointed both modals at
it — and promptly demonstrated the problem again, by carrying the create
modal's phone allowlist over to edit and locking out `+1 555 123 4567`
(caught in review on #60).

So shared validation was the right first move, but it only covers the rules.
The two forms still duplicate everything else.

## What is still duplicated

`CreateRestaurantModal/index.tsx` (278 lines) and `EditRestaurantModal/index.tsx`
(224) each hold:

- the same **ten `useState` field declarations** — name, price, address, city,
state, zipcode, country, phone_number, website, description;
- the same **ten inputs**, including the price `` with its five
options and the description `` with its `n/500` counter, differing
only in that create uses `placeholder` and edit uses a `<span>` label;
- the same **error list** and **submitting/saving button state**.

Genuinely different, and not worth forcing together:

- **create** has the cover-photo picker (upload vs URL, `uploadImage`, the
`image-picker` tabs) and navigates with `history.push` on success;
- **edit** is wrapped in an owner gate ("You are not the owner" / "Please log
in to update the restaurant") and calls `closeModal()` on success;
- their CSS is independent (`add-restaurant-form` vs `update-restaurant-form`).

## Suggested shape

A presentational `RestaurantForm` owning the ten fields and their markup:

```tsx
<RestaurantForm
value={fields} // RestaurantFields, already defined in restaurantValidation.ts
onChange={setFields}
labels="placeholder" | "inline" // the one real rendering difference
errors={errors}
busy={isSubmitting}
submitLabel={...}
onSubmit={...}
>
{/* create passes the cover-photo picker as a child */}
</RestaurantForm>
```

`RestaurantFields` already exists in `restaurantValidation.ts` and is the
natural state shape, which would also collapse the ten `useState` calls into
one.

Each modal keeps what is actually its own: create keeps the upload flow and the
redirect, edit keeps the owner gate and the modal close.

## Worth knowing before starting

- This is a refactor with **no user-visible change**, so it should be
reviewable as one.
- `EditRestaurantModal` now has component tests
(`components/EditRestaurantModal/index.test.tsx`, 7 cases covering the save
lifecycle) and the rules have `utils/restaurantValidation.test.ts` (19
cases). They should pass untouched afterwards — if the refactor needs them
rewritten, that is a signal it changed behaviour. `CreateRestaurantModal` has
no component tests yet; adding the equivalent ones first would make this
safer.
- Both modals' CSS keys off the form class names, so either keep those on the
wrapper or move the styles with the component.

## Why it is not urgent

The rules — the part that actually drifted, twice — are shared already, and the
remaining duplication is markup that changes rarely. This is about stopping the
next divergence cheaply, not fixing a live bug.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with CreateRestaurantModal/index.tsx and EditRestaurantModal/index.tsx, then read RestaurantFields in react-app/src/utils/restaurantValidation.ts and the existing EditRestaurantModal and validation tests. The refactor is done when both modals use one presentational RestaurantForm while retaining their distinct upload, owner-gate, navigation, and close behavior, with the existing tests still passing.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.