Skip to content

Optimize/landing - #635

Closed
DavidK4leido5 wants to merge 105 commits into
devfrom
optimize/landing
Closed

DavidK4leido5 wants to merge 105 commits into
devfrom
optimize/landing

Conversation

@DavidK4leido5

Copy link
Copy Markdown
Collaborator

No description provided.

deocagunot and others added 10 commits July 14, 2026 19:37
The Be a Member page filtered developers on role_id 10, but the accept flow
sets role_id 4 (Intern). Accepted developers therefore never appeared there,
and whoever still held the legacy role_id 10 showed up instead — the "iba ung
devs rendered" report.

application_status is the reliable signal: the accept flow always sets it to
"passed", while role_id tracks the Intern → Codev → Mentor progression and
changes as a developer advances. Filtering on it matches what /profiles already
does, so both public pages now read from the same source of truth.

The existing post-filter is unchanged and still removes admins, failed and
applying codevs, then narrows to active — so no one who should be hidden
becomes visible.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix(codevs): show accepted developers on Be a Member (cherry-pick to prod)
Enrollment generated 10 recovery codes with Math.random(), showed them in
a modal telling users to store them safely, and never persisted them. The
2FA challenge screen's backup-code branch was a placeholder that rejected
every code unconditionally, so no code could ever work. Users who enabled
2FA and lost their authenticator were left holding codes that did nothing.

Removes the backup-code path from the challenge form and replaces the
recovery-code modal with an honest confirmation that says recovery codes
are not available yet and losing the device means asking an admin to reset
2FA.

The TOTP flow is unchanged — the middleware assurance-level check and
challengeAndVerify were correct and are left alone. Real recovery codes
are specced separately in
docs/tasks/Jury-FS/2FA-Recovery-Codes-Are-Non-Functional.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…overy-codes

fix(2fa): remove non-functional backup recovery code UI (cherry-pick to prod)
@vercel

vercel Bot commented Aug 22, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
codebility-plus-codebility-portal Ready Ready Preview Sep 22, 2026 7:43am UTC

Request Review

AccountSettingsUsername: the mount fetch is a query and the debounced
availability typeahead is a query keyed on the debounced value, replacing
a timer-managed effect.

Settings profile, hire and admin-controls: mount fetches become queries;
JobListingsTable mutations write through the cache; TicketManagementView
derives the selected ticket instead of syncing it in an effect.

Also types ProfilePointsResponse.points as the row it actually is, so
consumers stop narrowing it inline.

dataFetchingEffects 14 -> 11
Certificate preview derived the certificate name/type in an effect and
fetched users and points in two more; all three become queries keyed on
the viewed user, with the editable name held as a draft.

MeetingBasedAttendance mirrors the attendance grid: the month travels
with the editable draft so a month change re-derives during render.

MyTeamPage drops the client-instance-in-state effect; 2FA factors are a
query the enrolment path invalidates.

dataFetchingEffects 11 -> 7
AddMembersModal's roster load, ChecklistManageModal's template load and
the test route's projects fetch become queries. The add-members
reset-on-close effect is deleted: the parent mounts that modal only while
open, so it was unreachable.

The four remaining data-fetching effects are all Rule-2 synchronisation
and are intentionally kept: the dashboard codev_points realtime channel,
notification polling plus realtime, the test route's live clock, and the
survey widget's one-shot imperative modal open.
The plan flags mutating actions with no revalidatePath as more dangerous
now that staleTimes holds the client Router Cache longer, and asks for
them to be fixed on any route touched. /home/hire's table and the
my-team attendance/member-points queries both read data these actions
write, so a delete or status change would otherwise leave the table
showing the old rows.

Five hire mutations and both attendance sync paths now revalidate.
staleTimes holds the client Router Cache for a long window, so an action
that writes without invalidating leaves the page showing pre-mutation
rows. Nine action files were missing it: news banners, survey questions,
services, promote-modal, ticket-support, dashboard timers and schedule,
attendance warnings, reapply, and signup.

A script now reports any mutating action file with no invalidation; it
reads 35/35 covered, and it recognises the kanban helper so that file is
not a false positive.
Four of five useEditor calls omitted the flag, so Tiptap logged an SSR
warning per render and dropped the subtree to a client render, which
shows as a hydration mismatch. TaskEditModal already had it; the other
four call sites now match.

Verified by console capture on /home/overflow with the composer open:
18 warnings before, 0 after.
A project with no team_leader row is a normal state, but .single() reports
it as PGRST116 'The result contains 0 rows', which the code then logged as
'Error fetching team lead' on every /home/my-team load. maybeSingle returns
null, which the existing !data?.codev branch already handles.

Verified by console capture: the error fires before, and is absent after.
Keeps the probes that established each fix rather than the throwaway
edit scripts: the landing pagination flow, the Tiptap console capture,
the project-member error capture, and the revalidation audit.
/home/announcements is a component directory, not a route, so probing it
only ever hit the 404 page. The modal opens from the navbar button on any
/home page, which is what this exercises: it loads its tabs from the
database and reports no errors.
Filters on /home/in-house and /home/interns never reached the server. A filter
change built a new query key, TanStack handed it initialData, and with no
initialDataUpdatedAt it counted as fresh under staleTime: 60s, so queryFn never
ran and the table rendered the unfiltered seed forever.

- usePaginatedQuery takes initialDataKey and seeds only on an exact hashKey match
- both pages render pageSize-matching pages, so the server seed and the client's
  first request describe the same rows
- add hooks/ui/use-debounced-value and debounce in-house search before it enters
  the key; 7 chars now issue 1 request

Measured /home/in-house: search Shaina 10->1 rows, 1 request; dropdown GRADUATED
10->9 rows, 1 request
The route awaited every project and sliced the page in the client, so the first
paint shipped the whole table.

- getProjectsPage filters the many-to-many category relation in the database and
  returns Page<Project>; the card's own columns only (main_image, not a
  nonexistent image_url), members hydrated by the existing two-query shape
- ProjectCardContainer drops usePagination and the tabPages map for
  usePaginatedQuery keyed on category + page

Measured: 12 cards rendered, tab Web Application -> 1 request, cards changed.
The page awaited every client and sliced page 1 in the browser.

- getClientsPage pages and counts in the database, ordering active-first there
  instead of sorting after the fetch
- ClientsCard drops usePagination for usePaginatedQuery keyed on page, with a
  skeleton gated on isPending rather than data length

Measured: 7 clients (whole set) render, 0 page errors.
The route awaited every task and sliced 9 per page in the browser, and derived
totalPages from the array in an effect.

- getTasksPage pages and counts in the database, filtering by codev_id directly
  (the old .single() codev lookup failed for users without a codev row)
- TasksContainer drops the slice and the effect for usePaginatedQuery keyed on
  codevId + page

Measured: 9 cards, 0 page errors, dataFetchingEffects unchanged at 3.
The route fetched every non-passed codev with select('*') plus the full applicant
join, then filtered the array in a useEffect on every keystroke.

- getApplicantsPage pages and counts per pipeline status in the database, with
  an explicit column list matching what newApplicantsSchema requires and the
  table renders; getApplicantStatusCounts gives the tab badges real totals
- ApplicantLists pages per tab with usePaginatedQuery, debounced search, and no
  effect; the header is now just the search field
- delete applicantFilters, applicantFiltersBadge and applicantSorters: they
  re-filtered the whole table in the browser and nothing else imported them

Measured: tabs show Applying 2 / Onboarding 4 / Waitlist 7 / Denied 1044;
search DAVID -> 4 rows to 2 on 1 request for 5 chars.
news-banners and surveys both fetched every column of every row to render cards
that use ten fields each. Column lists now match their row interfaces.

The five select('*') calls in settings/profile feed one user's own record into
six edit forms; enumerating columns there couples the page to every field a form
touches, so they stay (plan 5.1).

Measured: surveys and news-banners both render their real rows, 0 page errors;
p9-role-check allMatch true.
MemberChecklist fetched every column of every checklist row in the project to
render eleven fields. The column list now matches its ChecklistItem interface.

Left alone: MemberRating and ChecklistManageModal both use .limit(1).single(),
and AddMembersModal already debounces its typeahead at 300ms (plan 5.1, 4.4).
…w search

certificate-preview was a client page.tsx that read the viewer's skill and
attendance points from the browser after hydration.

- new read-only getCodevPointsSummary (cache()); deliberately not
  computeProfilePoints, which scores profile completeness and writes on read
- page.tsx is now a server shell that resolves the viewer and seeds the client
  island; admins switching users still fetch that user (F3)
- browser REST calls on first paint: 3 -> 1 (the remainder is the admin picker)

overflow search filtered only the five loaded rows and issued no request.

- fetchQuestions takes a search term and filters server-side, so a term matches
  every post; explicit column list replaces select('*')
- OverflowView pages and searches through a keyed useQuery seeded by the server
  render, with optimistic like/edit/delete writes into the query cache
- skeleton no longer gates on isFetching, which flashed over live rows

Measured /home/overflow: search 'zzzz' 15 -> 4 cards on 1 request (was 0).
columns.ts imported revalidateKanbanBoardLists but never called it, so creating,
renaming, moving or deleting a column left every cached board stale. updateTask
was the one mutating function in tasks.ts with no invalidation, and saveDraft
and deleteDraft had none either.

The p9 audit reported 35/35 covered because its pattern matched the import line.
Coverage is now per mutation: columns 4/4, drafts 5/5, tasks 11/11.

No kanban refactor: a missing revalidate is cache correctness (plan 3, 5.1).
PersonalInfo fetched the positions reference table on mount even though the
profile page already renders on the server. Positions now arrive as a prop from
the cached getPositions in lib/server/reference-data.ts, and the duplicate
select('*') copy in actions/settings/profile.ts is gone.

getEducation and getJobStatuses take explicit column lists matching what their
callers read.

Left alone: codev-queries.ts select('*') is a default parameter callers override,
and the two in feeds/post.ts are head:true count queries that return no rows.
TaskCard read a status variable that was never destructured, so the server
render threw ReferenceError and React fell back to client rendering for the
whole route. The block was dead: Task has no status field.

Found by looking at page text rather than the row count; the card grid still
rendered nine rows through the client fallback.

This branch was successfully deployed

1 active deployment
Preview — 1bce8112 Deployed Sep 22, 2026 by vercel[bot]
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.

2 participants