Commit Graph

374 Commits (2e0e6b1ddaa40f6c8327d482a45f99ec7dcd23ca)

Author SHA1 Message Date
ahmed.mujtaba ecd9b3597a form integrated 2026-08-27 17:32:03 +05:00
Talha Ahmed ccec7d48db Job cover images: move storage from disk into the database
Deploy to S3 / deploy (push) Successful in 31s Details
Production containers have ephemeral filesystems, so the disk-backed
image from the previous commit would vanish on redeploy. New
job_post_images table (bytea, PK = job_posts FK so re-upload replaces),
created everywhere by manual migration 009 which run_manual_sql applies
automatically at startup — prod boots with DB_AUTOGENERATE=false and
never autogenerates tables. Upload/fetch endpoints unchanged for the
frontend; fetch now serves bytes from the row. The one locally stored
disk image was imported into the table and backend/uploads removed.

E2E re-verified: create-with-image 200, fetch 200, cover renders.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 16:34:04 +05:00
ahmed.mujtaba fe80fa9fdc . 2026-08-27 16:20:12 +05:00
Talha Ahmed e6a82aaa23 Job posts: persist and display the cover image
Deploy to S3 / deploy (push) Successful in 32s Details
The create modal collected an image but dropped it. Now POST
/job/image/upload stores it on disk keyed by the post id (uuid-validated,
5 MB / png-jpg-webp-gif, replace-on-reupload; no DB migration) and GET
/job/image/fetch serves it. The create flow uploads right after the row
exists, image failure downgrades to a toast instead of failing the create,
and Job Details renders the cover via an authorized blob fetch.

E2E-verified: upload 200, fetch 200, cover renders in Job Details.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 16:17:55 +05:00
Talha Ahmed c22ea4c689 Job posts: remove the salary field
Deploy to S3 / deploy (push) Successful in 36s Details
Dropped from the create and edit modals, the detail drawer, the frontend
job mapper, and the composed publish text (which otherwise printed
Salary: Anonymous on every post). Backend model/API still tolerate the
column, so older clients and stored rows are unaffected.

UI-verified live: modal has no salary field, create POST carries no
salary key, cover-image upload previews and the post lands successfully.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 16:09:30 +05:00
ahmed.mujtaba d5879a0617 Refactor Google Sheets service integration
- Updated the `app.py` file to replace the generic `Sheet` service with specific services: `SheetHealth`, `SheetRead`, `SheetImport`, and `SheetWrite` for better clarity and functionality.
- Modified the `tasks.py` file to utilize the `SheetImport` service for handling sheet import tasks.
- Enhanced the `views.py` file by introducing a new class hierarchy for sheet operations, improving code organization and readability.

These changes improve the structure and maintainability of the Google Sheets integration.
2026-08-27 14:51:59 +05:00
Talha Ahmed 95b5de1635 Vite dev proxy: serve the SPA shell for browser navigations to API-prefixed routes
Deploy to S3 / deploy (push) Successful in 36s Details
Several API prefixes double as SPA routes (/jobs, /inbox, /pipeline, ...);
refreshing the browser on one proxied the navigation to the backend and
500d. Navigations send Accept: text/html and now bypass to /index.html,
while fetch/XHR traffic still proxies. VITE_API_TARGET repoints the proxy
when the API is not on 8000.

Verified: direct loads of /jobs, /inbox, /pipeline, /analytics, /offers
render the correct screen with the session intact; /health still proxies.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 11:46:28 +05:00
Talha Ahmed bc97182a7e Typography check: align inline hero numbers with the display type system
Full-app verification tour (25 screens, light + dark) confirmed Inter
Tight/Belleza/Inter render correctly; the only stragglers were inline
weight-800 numbers with px tracking in four screens, now on the same
display face, weights, and em tracking as the CSS system.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 11:41:00 +05:00
Talha Ahmed 9df3b46aa9 Typography overhaul: Inter Tight display headings, Belleza confined to wordmark
Belleza (single-weight decorative face) read thin and informal against
the dense data UI. Headings now use Inter Tight semibold with negative
tracking; hero metrics join the display face at proper optical sizes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 11:31:19 +05:00
Talha Ahmed abc8bffb81 frontend dist: bump built asset hashes
Deploy to S3 / deploy (push) Successful in 1m14s Details
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-27 10:46:21 +05:00
Talha Ahmed 5555f2475c Inbox queue rows: stop the sender name flooding the timestamp
The 380px queue rail left .ii-main only 148px: an email-style sender
name (no break points, never truncated) painted straight over the
timestamp, and the meta chips wrapped one per line. Three changes,
verified live against the dev server:

- Sender names truncate with the full value in title="" (Inbox and
  Matching, which reuses the row classes).
- Older-than-a-week list timestamps show the date only, like Outlook —
  the date+time form was ~105px and the detail pane has the full
  instant. .ii-main grows 148 -> 195px; both status chips fit one row.
- .ii-name gets min-width: 0 and its size joins the type scale.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 22:22:35 +05:00
Talha Ahmed 066346af80 ui-polish 7: hardening pass — skeletons, ErrorBoundary, auth font fix
- Skeleton loading system: .skeleton shimmer primitives in CSS (theme-
  aware via --border) plus a SkeletonRows component, adopted at the
  main-content loading states of Jobs, Candidates, Inbox, Interviews,
  Offers, Assessments, Tasks, Managers, Notifications. Small card-level
  loading states keep their EmptyState text.
- ErrorBoundary around the route outlet, keyed by pathname: a throw in
  one lazy screen shows a recoverable error state instead of blanking
  the whole app; navigating away resets it.
- auth.css stops hardcoding the Belleza stack twice; both sites use
  var(--font-display) so the display face has one definition.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 21:58:34 +05:00
Talha Ahmed 967c1acc5c ui-polish 6/6: responsive consolidation
- .g-3 grids step 3 -> 2 columns at 1200px and 2 -> 1 at 900px; they
  used to jump straight to one column, wasting the whole 900-1200 band
  (Managers cards, Help topics, JobBoard destinations).
- The four scattered trailing @media 640px fragments (Dashboard v2
  grid, candidate page, hiring forms) merged into ONE labeled block at
  the end of the file, positioned after every base rule; the paired
  400px override moves with it so small-phone rules still win. The
  core shell 640 block stays put so the landscape-phone height rules
  keep their existing precedence.
- Every breakpoint labeled; responsive section header updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 21:55:00 +05:00
Talha Ahmed c4793479a2 ui-polish 5/6: a11y semantics and remaining labels
- All 28 <div className="form-section-title"> section markers are real
  <h3> headings now — the class carries every visual property, so this
  is semantics-only, zero visual change.
- Remaining icon-only .act-btn buttons labeled: CandidateProfile
  (download/edit note/revise scorecard, incl. one that had neither
  tooltip nor label), CandidateForms amend button.
- PasswordField show/hide toggle is keyboard-reachable (tabIndex -1
  removed) with aria-pressed state.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 21:53:08 +05:00
Talha Ahmed af6ef715c5 ui-polish 4/6: screen sweep B (17 remaining page screens)
AiAssistant, AiStudio, Analytics, Assessments, Calendar, CvImport, Help,
JobBoard, Notifications, Offers, Pipeline, Rbac, RecruiterHub, Reports,
Talent, TalentPool, Tasks — same bounded checklist:

- Every remaining hand-rolled .page-head replaced with <PageHeader/>;
  zero copies of the block remain in the codebase.
- JobBoard fixes its non-functional inline ellipsis (overflow without
  white-space never truncated) with .truncate + title.
- Tasks imports the shared PRIORITY_CLASS and labels its unlabeled
  card-head add button; remaining .act-btn tooltips mirrored into
  aria-labels (Assessments, JobBoard, Notifications, Offers, Talent).
- Assessments swaps a hand-rolled empty state for the imported
  EmptyState; Help drops an inline h2 font size the base rule now covers.
- Mechanical inline-style swaps to utilities on exact matches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 21:51:26 +05:00
Talha Ahmed 4757895029 ui-polish 3/6: screen sweep A (9 representative screens)
Dashboard, Candidates, Jobs, Settings, Inbox, Interviews, Matching,
Managers, JobCandidates — bounded checklist per screen:

- Hand-rolled .page-head blocks replaced with <PageHeader/>. Fixes
  Matching, whose bare <h1> rendered in the wrong face and weight.
- Candidates drops its verbatim copy of the DataTable thead for
  DataTableHead; clickable rows use .row-click.
- Interviews deletes its local STATUS_CLASS shadow (Badge auto-maps
  identically); Dashboard imports the shared PRIORITY_CLASS.
- Icon-only .act-btn buttons gain aria-labels mirroring their tooltips.
- Emails no longer overflow: Settings/Candidates clip with full text in
  title=""; Managers shows the full address again instead of chopping
  the domain off the data.
- Mechanical inline-style swaps to the new utilities (mb-*, mt-*,
  flex-1, justify-between, flex-wrap) on exact matches only.
- Settings uses its imported EmptyState instead of a hand-rolled copy;
  JobCandidates embedded title uses .page-title-sm instead of an inline
  font size.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 21:46:11 +05:00
Talha Ahmed bd16f8a775 ui-polish 2/6: PageHeader, DataTable dedup, Tabs/Toast/Dropdown a11y
- New ui/PageHeader.jsx emitting the existing .page-head structure;
  screens adopt it in the next two passes.
- DataTable: sortable thead extracted as DataTableHead (Candidates can
  drop its verbatim copy) and an onRowClick prop with keyboard support.
- Tabs: index-based ids, aria-controls, roving tabindex, arrow-key and
  Home/End navigation; TabPanel labels its panel.
- Toast root announces politely to screen readers (was silent).
- Dropdown stamps aria-expanded/aria-haspopup on every trigger.
- primitives: shared PRIORITY_CLASS (Dashboard and Tasks had identical
  private copies).
- Shell: skip link to #main-content, sidebar nav labeled Primary,
  clickable notification rows are real buttons now.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 21:39:31 +05:00
Talha Ahmed bc5856005d ui-polish 1/6: typography+spacing tokens, base headings, utilities
- Type scale (--fs-2xs..--fs-3xl) and line-height tokens; the 20-size
  census collapses onto 9 steps. Spacing scale (--space-1..8) plus --gap
  keeping the signature 18px rhythm. Colors untouched.
- Base h1-h6 rules: bare headings used to render at UA defaults, larger
  and bolder than the styled card titles beside them.
- One eyebrow-label rule replacing eleven near-identical declarations at
  five sizes and five letter-spacings.
- High-traffic families retrofitted to tokens (page/card/table/form/btn/
  tabs/badge/sidebar/kpi); rare bolt-on sections left alone.
- New utilities: truncate, clamp-2, justify-between, flex-wrap, flex-col,
  flex-1, min-w-0, w-full, mt/mb-8/12/16/24, cell-clip, row-click.
- Defined phantom classes shipped in JSX (.dt, .route-loading,
  .tab-count) and a .skip-link.
- Email/role cells clip with ellipsis on all viewports, not only <640px.
- Content measure capped at 1440px on every desktop, not only >=1600.
- Sidebar: clearer group separation, active item weight 600.
- main.jsx design-contract comment amended: colors stay frozen,
  typography/spacing re-tokenized.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 21:37:14 +05:00
ahmed.mujtaba 6f52436165 . 2026-08-25 20:18:12 +05:00
ahmed.mujtaba ddfbb00edf Merge branch 'RELIMIt' of https://git.utopiadeals.com/utopia-ai/HR-ATS-Portal into RELIMIt 2026-08-25 20:11:05 +05:00
ahmed.mujtaba 65c189a6db . 2026-08-25 20:11:02 +05:00
Talha Ahmed 4ad964e1ff Talent filter uses the standard toolbar-search box
className="input" matches no CSS rule, so the filter fell back to the
browser default ~180px width and clipped its own placeholder ("Filter
by name, headline, com"). Swap it for the toolbar-search pattern every
other screen uses: search icon, full-width input, 340px cap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 19:49:08 +05:00
Talha Ahmed cec3be73fb Title tier of relevance_score accepts token containment
Live case: the job titled "Generative Engineer" sourced a pool titled
"Generative AI Engineer" -- the exact phrase never occurs in that title,
so every genuine match fell through to the scattered 35 tier and the
whole pool compressed into the 40s. A current title containing every
job-title token now earns the full 55. The headline tier stays
phrase-only so keyword-stuffed headlines still cap at the 35 tier.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 19:46:34 +05:00
ahmed.mujtaba 031261f179 Merge pull request 'implemented semaphhore' (#28) from RELIMIt into main
Deploy to S3 / deploy (push) Successful in 35s Details
Reviewed-on: #28
2026-08-25 12:31:16 +00:00
ahmed.mujtaba 21a85927e4 Merge branch 'main' into RELIMIt 2026-08-25 12:31:09 +00:00
ahmed.mujtaba a0ab618ac5 implemented semaphhore 2026-08-25 17:29:44 +05:00
ahmed.mujtaba 19d302325b Merge pull request 'RELIMIT' (#27) from RELIMIt into main
Deploy to S3 / deploy (push) Successful in 37s Details
Reviewed-on: #27
2026-08-25 12:03:10 +00:00
ahmed.mujtaba a02b7aa8c3 RELIMIT 2026-08-25 17:01:46 +05:00
ahmed.mujtaba 39af6445b4 Merge pull request 'Implementing_limitListing' (#26) from Implementing_limitListing into main
Deploy to S3 / deploy (push) Successful in 40s Details
Reviewed-on: #26
2026-08-25 07:56:35 +00:00
ahmed.mujtaba d9992e46d1 correct the error 2026-08-25 12:54:04 +05:00
ahmed.mujtaba 347856e8f8 Update environment management by removing `.env.example` and refining Docker configurations
- Deleted the `.env.example` file to centralize configurations in `backend/.env`.
- Adjusted `docker-compose.yml` and `docker-compose.dev.yml` for improved environment variable handling.
- Enhanced nginx configuration for better API request management.

These changes streamline the setup process and improve configuration management.
2026-08-25 12:31:42 +05:00
ahmed.mujtaba 4da9d38ee8 Merge branch 'Implementing_limitListing' of https://git.utopiadeals.com/utopia-ai/HR-ATS-Portal into Implementing_limitListing 2026-08-25 12:29:26 +05:00
Talha Ahmed 2aa151f3e4 Restore /candidate_forms/ gitignore entry lost in merge
Deploy to S3 / deploy (push) Successful in 34s Details
Both branches appended at EOF; the merge kept only main's hunk and its
missing trailing newline. Root-anchored so backend/candidate_forms/
(the forms domain package) stays tracked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 22:23:26 +05:00
Talha Ahmed 9ffb3caa99 Merge remote-tracking branch 'origin/main' into Talha 2026-08-24 22:22:11 +05:00
Talha Ahmed 8bfd71194e Forms also unlock when the candidate has an interview scheduled
Scheduling an interview record did not move the pipeline stage, so
recruiters who booked an interview from the profile still saw the Forms
tab locked (reported on a Shortlist-stage candidate with a completed
Technical interview). The gate now passes when the stage is
INTERVIEW/OFFER/HIRED OR the application has any interview on record —
enforced server-side in candidate_forms create (manual-upload candidates
still unlock by stage alone, since interviews link only to inbox rows)
and mirrored in the Forms tab hint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 22:21:36 +05:00
ahmed.mujtaba f8685c04fe Add root .env.example Compose pointer (no secrets).
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-24 21:28:16 +05:00
ahmed.mujtaba 0a6dd688fb Stop tracking .env files so secrets are never pushed.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-24 21:25:23 +05:00
ahmed.mujtaba fb27ec3bb3 . 2026-08-24 21:25:09 +05:00
ahmed.mujtaba 09965f420f .
Deploy to S3 / deploy (push) Successful in 36s Details
2026-08-24 16:24:49 +00:00
ahmed.mujtaba 5dcc824d70 .
Deploy to S3 / deploy (push) Successful in 37s Details
2026-08-24 16:23:55 +00:00
ahmed.mujtaba fa1fb7c5a4 . 2026-08-24 16:23:00 +00:00
ahmed.mujtaba 22e98ebd4b ,. 2026-08-24 16:22:37 +00:00
ahmed.mujtaba a09f49d0f5 Merge pull request 'add .env vars' (#25) from Implementing_limitListing into main
Deploy to S3 / deploy (push) Successful in 36s Details
Reviewed-on: #25
2026-08-24 16:16:54 +00:00
ahmed.mujtaba 78f42011fc . 2026-08-24 21:15:59 +05:00
ahmed.mujtaba a3ea38ca5e Merge branch 'main' of https://git.utopiadeals.com/utopia-ai/HR-ATS-Portal into Implementing_limitListing 2026-08-24 21:15:21 +05:00
ahmed.mujtaba e114aeb0cf add .env vars 2026-08-24 21:05:53 +05:00
ahmed.mujtaba 2160059400 Merge pull request 'Implementing_limitListing' (#24) from Implementing_limitListing into main
Deploy to S3 / deploy (push) Successful in 35s Details
Reviewed-on: #24
2026-08-24 15:41:28 +00:00
ahmed.mujtaba f1597792ed tests rtemoved 2026-08-24 20:40:08 +05:00
ahmed.mujtaba 29c0362517 Merge branch 'main' of https://git.utopiadeals.com/utopia-ai/HR-ATS-Portal into Implementing_limitListing 2026-08-24 20:39:31 +05:00
ahmed.mujtaba 8c12872c6e Remove `.env.example` and update Docker configurations for environment management
- Deleted the `.env.example` file as it is no longer needed; all configurations are now centralized in `backend/.env`.
- Updated `docker-compose.yml` and `docker-compose.dev.yml` to reflect changes in environment variable handling, ensuring that the application reads from `backend/.env` exclusively.
- Adjusted the nginx configuration to improve API request handling and ensure proper proxying for frontend interactions.

These changes streamline the environment setup process and enhance the overall configuration management for local and production deployments.
2026-08-24 20:38:15 +05:00