Skip to content

adjustment as per new signup form in app - #151

Open
vvshk wants to merge 4 commits into
devfrom
feat/signup-form
Open

vvshk wants to merge 4 commits into
devfrom
feat/signup-form

Conversation

@vvshk

@vvshk vvshk commented Jul 5, 2026 •

Copy link
Copy Markdown
Collaborator

Update 3 Oct 2026: brought up to date and fixed (not merged)

  • dev merged in. The card edit screen keeps dev's Show and fill in the guest fields when staff edit a guest card #202 guest rules: the host is shown, can't be cleared, and the type is kept.
  • The reference-phone lookup now uses the staff-only by-mobile route with the token, checks res.ok, is debounced, ignores stale answers, and shows the host as text. It warns when the host isn't a Mumukshu.
  • Hidden fields are no longer submitted. The card number is made on save and shown after. Option values are escaped.
  • Tested in a browser (Playwright) against Feat/signup form aashray-backend#342 locally: Mumukshu, Seva Kutir with a department, guest by phone, edit keeps the host, and a bad phone shows the backend's error.
  • Needs Feat/signup form aashray-backend#342 deployed first.

@claude

claude Bot commented Jul 5, 2026 •

Copy link
Copy Markdown

Claude finished @vvshk's task in 4m 32s —— View job


PR Review: adjustment as per new signup form in app

I reviewed the diff against origin/dev (4 files, +742/−272). The refactor to reference-phone lookup + department/seva-kutir handling is solid and internally consistent, and the Prettier reformat is welcome. I left 6 inline comments — none are hard blockers, but two are worth resolving before merge.

  • Read repo conventions & context (no CLAUDE.md present)
  • Review admin/card/createCard.html
  • Review admin/card/createCard.js
  • Review admin/card/updateCard.html
  • Review admin/card/updateCard.js
  • Post inline findings & summary

Key findings (inline)

🟠 Should address

  1. Phone lookup skips auth & error handling — the checkMobile call hits the client API (CONFIG.baseUrl) with no Authorization header (every other request here sends a token; there's even an authenticated admin card/by-mobile endpoint). It also never checks res.ok, so a 401/500 renders as the misleading "Phone number is not registered!". createCard.js · updateCard.js
  2. updateCard submits stale referencePhone/guestType/department regardless of res_status, because hidden fields aren't cleared. Switching a GUEST/SEVA KUTIR card to MUMUKSHU still sends the old values. createCard.js already does this correctly (conditional attach). Inline + suggestion →

🟡 Worth confirming / nice-to-have
3. Empty cardno submitted — the field is now readonly/auto-generated but nothing sets its value, so cardno: "" is sent. Confirm the backend generates it (or omit the key). Inline →
4. No debounce + duplicated logic — the reference-phone handler fires per keystroke (out-of-order responses can show stale names) and is copy-pasted between the two files; consider a shared helper. Inline →

👍 Looks good

  • referencePhone / guestType / department field names are consistent across both forms and payloads.
  • Required-field validation for GUEST and SEVA KUTIR with early return + button re-enable; double-submit guard retained.
  • updateCard correctly awaits loadDepartments() before populating, so the saved department resolves to an existing option.

Note: I reviewed for correctness/conventions only and did not run a linter or tests (this is a static frontend with no test suite in the repo).
· feat/signup-form

Comment thread admin/card/createCard.js Outdated
Comment on lines +168 to +170
const res = await fetch(
`${CONFIG.baseUrl}/client/checkMobile/${val}`
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing auth header + no res.ok check on the phone lookup.

Every other fetch in this codebase sends Authorization: Bearer <token>, and there's already an authenticated admin endpoint for mobile lookups — ${CONFIG.basePath}/card/by-mobile/${mobno} (see admin/wifi/permanentCodeRequests.js:408). This new call instead hits the client API (CONFIG.baseUrl, not basePath) with no token.

  • If /client/checkMobile requires auth, this will 401. Because the code never checks res.ok and only reads data.exists, the admin will always see the misleading "Phone number is not registered!" message instead of an error.
  • Please confirm the endpoint is intentionally public. If it isn't, switch to the authenticated admin endpoint.

At minimum, guard on the response status:

Suggested change
const res = await fetch(
`${CONFIG.baseUrl}/client/checkMobile/${val}`
);
const res = await fetch(
`${CONFIG.baseUrl}/client/checkMobile/${val}`
);
if (!res.ok) {
nameEl.textContent = 'Error checking phone number';
nameEl.style.color = '#c62828';
return;
}

Comment thread admin/card/updateCard.js Outdated
Comment on lines +322 to +323
const res = await fetch(`${CONFIG.baseUrl}/client/checkMobile/${val}`);
const data = await res.json();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same phone-lookup concern as in createCard.js: this hits the client API (CONFIG.baseUrl) with no Authorization header — a deviation from every other request here — and never checks res.ok, so an error response silently renders as "Phone number is not registered!". Please verify the endpoint is public; otherwise use the authenticated admin lookup. A minimal safety guard:

Suggested change
const res = await fetch(`${CONFIG.baseUrl}/client/checkMobile/${val}`);
const data = await res.json();
const res = await fetch(`${CONFIG.baseUrl}/client/checkMobile/${val}`);
if (!res.ok) {
nameEl.textContent = 'Error checking phone number';
nameEl.style.color = '#c62828';
return;
}
const data = await res.json();

Comment thread admin/card/updateCard.js Outdated
Comment on lines +99 to +101
referencePhone: document.getElementById('referencePhone')?.value || null,
guestType: document.getElementById('guestType')?.value || null,
department: document.getElementById('department')?.value || null

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale data: referencePhone / guestType / department are always submitted regardless of res_status.

These fields are hidden (not cleared) when the status changes, and populateForm fills them from the fetched record. So editing a card that was a GUEST/SEVA KUTIR and switching it to MUMUKSHU/PR will still send the old reference phone / guest type / department to the backend.

createCard.js handles this correctly by only attaching these keys inside the matching res_status block. Mirror that here so irrelevant fields are sent as null:

Suggested change
referencePhone: document.getElementById('referencePhone')?.value || null,
guestType: document.getElementById('guestType')?.value || null,
department: document.getElementById('department')?.value || null
referencePhone:
document.getElementById('res_status').value === 'GUEST'
? document.getElementById('referencePhone')?.value || null
: null,
guestType:
document.getElementById('res_status').value === 'GUEST'
? document.getElementById('guestType')?.value || null
: null,
department:
document.getElementById('res_status').value === 'SEVA KUTIR'
? document.getElementById('department')?.value || null
: null

Comment thread admin/card/createCard.js Outdated
Comment on lines +161 to +191
refPhoneInput.addEventListener('input', async (e) => {
const val = e.target.value.trim();
const nameEl = document.getElementById('refPhoneName');
if (val.length === 10) {
nameEl.textContent = 'Checking...';
nameEl.style.color = '#777';
try {
const res = await fetch(
`${CONFIG.baseUrl}/client/checkMobile/${val}`
);
const data = await res.json();
if (data.exists) {
if (data.res_status === 'MUMUKSHU') {
nameEl.textContent = `Name: ${data.name} (Mumukshu)`;
nameEl.style.color = '#2e7d32';
} else {
nameEl.textContent = `Name: ${data.name} (${data.res_status}) - Warning: Not a Mumukshu`;
nameEl.style.color = '#c62828';
}
} else {
nameEl.textContent = 'Phone number is not registered!';
nameEl.style.color = '#c62828';
}
} catch (err) {
nameEl.textContent = 'Error checking phone number';
nameEl.style.color = '#c62828';
}
} else {
nameEl.textContent = '';
}
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two smaller points on this listener:

  1. No debounce / out-of-order responses. A request fires on every keystroke once the value hits 10 chars (and again on each subsequent edit). Since responses are async, a slower earlier request can resolve after a later one and overwrite the label with stale data. Consider debouncing, or tracking the latest query and ignoring outdated responses.
  2. Duplication. This inline handler is a near-exact copy of checkReferencePhone() in updateCard.js. Extracting a shared helper (or reusing the same function name/logic) would keep the two forms in sync as this evolves.

Neither blocks the PR, but worth cleaning up while the code is fresh.

Comment thread admin/card/createCard.html Outdated
Comment on lines +56 to +57
placeholder="Auto-generated"
readonly

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cardno is now readonly / auto-generated and lost its previous required + pattern="[0-9]{10}". Nothing in createCard.js populates this field, so the submit handler sends cardno: form.cardno.value as an empty string (createCard.js:231).

Please confirm the /card/create backend treats an empty cardno as "generate one". If it still validates the format, "" will be rejected; if it auto-generates, consider dropping cardno from the request payload entirely to make the intent explicit.

Conflicts in the card edit screen keep dev's #202 guest fields (host shown,
can't be cleared, type kept). On top of that:
- The reference-phone lookup (new refPhone.js) uses the staff-only by-mobile
  route with the staff token, checks res.ok, is debounced, ignores stale
  answers, and shows the host's name and type as text. It warns when the host
  is not a Mumukshu and says "not registered" for an unknown phone.
- Create: the card number box says it is made on save, and the new number is
  shown after create. Seva Kutir cards get a department.
- Edit: hidden department and phone fields are no longer submitted.
- API values put into option lists are escaped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@claude

claude Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Claude finished @vendz's task in 1m 8s —— View job


PR Review (second pass, after the new push)

  • Read the PR diff against origin/dev (5 files, +368/−205)
  • Review refPhone.js (new)
  • Review createCard.html / createCard.js
  • Review updateCard.html / updateCard.js
  • Post inline comments and this summary

Earlier review comments, now fixed ✅

Earlier finding Status
Phone lookup sent no token and never checked res.ok ✅ It now calls the staff-only /admin/card/by-mobile endpoint with the token. 404 shows "not registered" and other errors show their own message
No debounce, and late answers could overwrite the label ✅ It waits 400 ms after typing stops, and a latest check drops answers for an old number
Phone check copied into both card screens ✅ Both screens now use the shared attachRefPhoneCheck() in refPhone.js
updateCard sent old reference/department values ✅ It sends department only for SEVA KUTIR and referencePhone only for a guest with a blank card number
Dropdown options built from raw API strings ✅ escapeHtml() is now applied to every <option>

New inline comments

🟠 Should fix

  1. Duplicate city lookups after changing country: fetchStates adds another change listener to #state on every call, and each listener uses the country it was created with. After switching country, changing the state runs several city lookups at once, and the city dropdown can end up with duplicates or cities from the wrong country. This bug was already there before this PR, but the lines are touched here. Inline →
  2. The reference phone format isn't checked: a 5-digit number or text passes the empty check and goes to /card/create. Add maxlength="10" pattern="\d{10}" here and in updateCard.html:201. Inline →

🟡 Nit
3. refPhone.js:19 builds the URL as ${CONFIG.baseUrl}/admin/... but the other by-mobile calls use CONFIG.basePath. Inline →
4. createCard.js:61 still sends cardno: "", because the field is read-only and nothing fills it in. If the backend makes the card number (the new success alert reads result.data?.cardno), remove this key from the request. GitHub wouldn't let me put an inline comment here because line 61 isn't part of the diff.

Things to check with the backend

  • In updateCard, switching a card away from SEVA KUTIR sends department: null. Make sure the backend reads null as "remove the department" and not "leave it unchanged".
  • On the update screen, a typed reference phone is ignored whenever the reference card field has a value. The placeholder says so, but the screen doesn't warn staff if they fill in both.

👍 Looks good

  • refPhone.js is small and does one job: a 404 shows "not registered", other errors show their message, and a host who isn't a Mumukshu gets a separate warning colour.
  • populateForm adds the saved department to the list even when /location/departments doesn't return it, so a saved department never shows as blank.
  • The guest-type rules (hasReference now also counts a typed phone) are handled consistently on both screens.

This was a read-only review. I didn't run a linter or tests because the repo has neither for these static pages.
· feat/signup-form

Comment thread admin/card/createCard.js Outdated
Comment on lines +193 to +195
stateSelect.addEventListener('change', () =>
fetchCities(country, stateSelect.value)
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate change listeners on the state dropdown (this bug was already there; you only reformatted it, but it's worth fixing while you're here).

Each call to fetchStates adds another listener to #state, and each one keeps the country it was created with. If staff pick country A and then switch to country B, changing the state calls fetchCities(A, state) and fetchCities(B, state) at the same time. Both requests then append to #city, so the dropdown can show duplicate cities or cities from the wrong country. The country listener at line 160 isn't affected because loadLocationData runs only once.

Fix: read the current country when the event fires. Either register the listener once, outside fetchStates, or set the handler property so it replaces the old one:

Suggested change
stateSelect.addEventListener('change', () =>
fetchCities(country, stateSelect.value)
);
stateSelect.onchange = () =>
fetchCities(document.getElementById('country').value, stateSelect.value);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied in 7bfc0c2.

Comment on lines +271 to +276
<input
type="text"
id="reference_phone"
name="reference_phone"
class="form-control"
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reference phone isn't checked for format. refPhone.js only looks up the host when the value is exactly 10 characters, but nothing stops the form from being submitted with 12345 or letters in it. assignCard only checks that the field isn't empty, so a bad number goes straight to /card/create. Use the same limits as #mobno:

Suggested change
<input
type="text"
id="reference_phone"
name="reference_phone"
class="form-control"
/>
<input
type="text"
id="reference_phone"
name="reference_phone"
class="form-control"
maxlength="10"
pattern="\d{10}"
/>

(updateCard.html:201 should get the same maxlength/pattern. An empty field still passes pattern, so it stays optional there.)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied in 7bfc0c2.

Comment thread admin/card/refPhone.js Outdated
show('Checking...', null);
try {
const res = await fetch(
`${CONFIG.baseUrl}/admin/card/by-mobile/${encodeURIComponent(phone)}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this builds the same URL as the other by-mobile callers, but in a different way. Those use CONFIG.basePath (utsavRegistration.js:239, permanentCodeRequests.js:408). Using it here too means the admin prefix is defined in one place only.

Suggested change
`${CONFIG.baseUrl}/admin/card/by-mobile/${encodeURIComponent(phone)}`,
`${CONFIG.basePath}/card/by-mobile/${encodeURIComponent(phone)}`,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied in 7bfc0c2.

- The state dropdown has one handler that reads the current country, so a
  country switch no longer runs duplicate city lookups for the old country.
- The reference phone must be 10 digits (maxlength and pattern) on create
  and edit.
- The phone lookup builds its URL from CONFIG.basePath like other callers.
- Create no longer sends an empty cardno; the backend makes the number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vendz

vendz commented Oct 3, 2026

Copy link
Copy Markdown
Member

Review round 1 handled in 7bfc0c2. Create no longer sends cardno, since the backend makes it. Checked against SRATRC/aashray-backend#342: an update to a card that isn't Seva Kutir clears the department, so department: null is fine. Re-tested in a browser: one city lookup per state change after a country switch, and a 5-digit reference phone is refused.

@claude

claude Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Claude finished @vendz's task in 1m 2s —— View job


PR Review (third pass, after commit 7bfc0c2)

  • Read the PR diff against origin/dev (5 files, +371/−206)
  • Check the fixes for the earlier review comments
  • Review the full diff for anything new
  • Post inline comments and this summary

Second-pass comments, now fixed ✅

Earlier finding Status
Duplicate change listeners on #state used an old country ✅ Now uses stateSelect.onchange, which reads the current #country when the event fires (createCard.js:193)
Reference phone format wasn't checked ✅ Both screens now have maxlength="10" pattern="\d{10}"
refPhone.js used CONFIG.baseUrl + /admin/... ✅ Now uses CONFIG.basePath
Create sent cardno: "" ✅ The key is removed from the request

New inline comments

🟠 Should fix

  1. A hidden invalid phone blocks Submit with no message. This comes from the new pattern. If staff type a partial number as a guest and then switch to another type, the hidden field still fails validation. The browser can't focus a hidden field, so it shows no message and nothing happens when Submit is pressed. Updating a card has the same problem. Fix: disable the phone input while it's hidden. Inline →

🟡 Worth fixing

  1. assignCard is attached twice: once by onsubmit in the HTML and once by addEventListener in the JS. A successful submit still sends one request because of the disabled-button guard. When validation fails, though, the alert shows twice, because the first call turns the button back on before the second call runs. This was already on dev, but the new Seva Kutir check also hits it. Inline →

Still to check with the backend (from the last pass)

  • updateCard sends department: null when a card moves away from SEVA KUTIR. Make sure the backend reads this as "clear it".
  • On the update screen, a typed reference phone is ignored when the reference card field also has a value. The placeholder says so, but staff aren't warned if they fill in both.

👍 Looks good

  • refPhone.js handles 404 separately from other errors, waits for a pause in typing, and drops answers for an old number.
  • Hidden fields are only sent for the matching type on both screens.
  • escapeHtml() is used on every option built with innerHTML. loadDepartments uses textContent/new Option.

Apart from item 1, the PR looks ready once SRATRC/aashray-backend#342 is deployed.

This was a read-only review. I didn't run a linter or tests because the repo has neither for these static pages.

Comment on lines +276 to +278
maxlength="10"
pattern="\d{10}"
title="Enter a 10 digit phone number"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A hidden phone that fails pattern blocks the save with no message. This comes from the latest commit.

How to reproduce: choose GUEST, type 12345 in this field, then switch to MUMUKSHU/PR/SEVA KUTIR and press Submit. #guestFields is hidden with display: none, but its input still has an invalid value, so the browser blocks the submit. Because the field can't be focused, Chrome shows no tooltip. It only logs "An invalid form control … is not focusable" to the console. Staff see a Submit button that does nothing.

updateCard.html:201 has the same problem, through .guest-only.

Fix: turn the guest inputs off while they are hidden, because disabled controls are skipped by validation. In toggleResStatusFields in createCard.js:

document.getElementById('reference_phone').disabled = res_status !== 'GUEST';

In updateCard.js → updateGuestFields():

document.getElementById('referencePhone').disabled = !isGuest;

(The submit code already reads these values only for GUEST, so disabling them doesn't change what gets sent.)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied in 677e965. Re-tested in a browser: a guest with 12345, switched to Mumukshu, saves on create and on update, and validation alerts show once.

Comment thread admin/card/createCard.html Outdated
@@ -45,14 +47,26 @@
<div class="form">
<form id="cardForm" onsubmit="assignCard(event)">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assignCard runs twice on each submit. It is called by this onsubmit attribute and also by addEventListener('submit', assignCard) in createCard.js:2. This was already true on dev, but this PR adds a new validation branch that makes it visible:

  • If the data is valid, the second call returns early because of the submitBtn.disabled guard, so only one request is sent. That case is fine.
  • If validation fails (a GUEST without a phone or type, or a SEVA KUTIR without a department), the first call shows the alert, turns the button back on, and returns. The second call then gets past the guard and shows the same alert again.

Keep only one of the two. The JS listener is the simpler one to keep:

Suggested change
<form id="cardForm" onsubmit="assignCard(event)">
<form id="cardForm">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied in 677e965. Re-tested in a browser: a guest with 12345, switched to Mumukshu, saves on create and on update, and validation alerts show once.

- Guest-only inputs (reference phone, guest type, reference card) are
  disabled while hidden, so a half-typed phone left in a hidden field no
  longer blocks Submit silently.
- The create form no longer has an inline onsubmit as well as the JS
  listener, so a validation alert shows once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@claude

claude Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Claude finished @vendz's task in 29s —— View job


PR Review (fourth pass, after commit 677e965)

  • Read the new commit and the full PR diff against origin/dev
  • Check the fixes for the third-pass comments
  • Look for new problems the changes could cause
  • Post the summary

Third-pass comments, now fixed ✅

Earlier finding Status
A hidden invalid reference phone blocked Submit with no message ✅ On create, toggleResStatusFields turns off #reference_phone and #guest_type unless the type is GUEST (createCard.js:128-131). On update, updateGuestFields does the same for #referenceCardno and #referencePhone (updateCard.js:197-199). The browser skips turned-off fields when it checks the form, so a half-typed number left in a hidden field no longer blocks Submit.
assignCard ran twice on each submit ✅ The onsubmit attribute is gone from createCard.html:48. Only the listener at createCard.js:2 is left, so a failed check shows its alert once.

Checked for side effects

  • Turned-off fields and the values sent: both submit functions read the guest fields only when the type is GUEST, and those fields are on in that case. A turned-off field's value can still be read in JS anyway, so nothing that gets sent changes.
  • Update screen, Show and fill in the guest fields when staff edit a guest card #202 guest rules: reference.required is still set only when isGuest, so turning the field off when the card isn't a guest doesn't change the rule that the host can't be cleared. guestType still follows !isGuest || !hasReference, the same as before.
  • Switching back to GUEST: the fields are turned back on, and any typed value is still there. updateGuestFields runs on every res_status change, so the state stays correct.

New issues

None. I didn't post any inline comments this time.

Still to check before merging

  • Feat/signup form aashray-backend#342 has to be deployed first. The new lookup, the card number the backend now makes, and department: null all depend on it. The last comment from @vendz confirms the backend clears the department when it gets null.
  • On the update screen, a typed reference phone is ignored when the reference card field also has a value. The placeholder says so, but staff aren't warned if they fill in both. This is a small UX point and doesn't block the merge.

👍 Looks good

The PR looks ready to merge once the backend is deployed.

I only read the code for this review. I didn't run a linter or tests, because the repo has neither for these static pages.
· feat/signup-form

This branch was successfully deployed

1 active deployment
feat/signup-form - aashray-admin PR #151 — 677e9653 Deployed Oct 3, 2026 by VitraagVigyaan
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants