RIC-136 — Candidates "select all" + redesigned toolbar (docs) Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Update docs/acquisti/step.mdx (and check faq.mdx) so the "Selezione fornitori" section matches the redesigned candidates-list toolbar — the Seleziona tutti i candidati / Cancella selezione button, the Filtra: toggles, Contatta Fornitori, and the per-card Aggiungi ai contatti — and re-capture the affected screenshots from the running app.
Architecture: Docs-only change in the factorybook-user-guide Docusaurus repo. Prose is rewritten from a verified model of the UI (webapp source). Screenshots are re-captured against the local ../factorybook stack using a new demo seeder that puts an RFQ into SELEZIONE FORNITORI. The Aggiungi ai contatti dialog is already documented in connessioni/elenco.mdx, so step.mdx only mentions it and cross-links.
Tech Stack: Docusaurus (MDX), pnpm; Laravel seeders (../factorybook/backend); chrome-devtools MCP for screenshots.
Reference: Spec at docs/superpowers/specs/2026-07-18-ric-136-candidates-select-all-design.md.
Global Constraints
- User-facing doc content is Italian; code, seeders, commit messages, and file names are English (per CLAUDE.md).
- UI labels must be copied verbatim from the app:
Aggiungi fornitori,Importa fornitori,Ricerca automatica,Seleziona tutti i candidati,Cancella selezione,Filtra:,Con quotazione,Con messaggi,Contatta Fornitori,Aggiungi ai contatti,Nei contatti. - Screenshots: viewport 1423×867 @2x, saved to
static/img/screenshots/with kebab-case Italian names. Reuse the existing filenames (acquisti-lista-candidati.png,acquisti-candidati-selezione-free.png,acquisti-candidati-stati.png) so MDX references don't change. - Demo account: [email protected] /
password, company Tecnomec S.r.l., viaDemoUserSeeder. Demo data must be realistic Italian (company names, provinces) — never lorem ipsum. - All docs-repo commands run in the worktree:
/Users/ricventu/code/Factorybook/factorybook-user-guide/.claude/worktrees/ricventu+ric-136-seleziona-tutti-nella-lista-candidati. Seeder/app commands run in/Users/ricventu/code/Factorybook/factorybook. - Docusaurus build must pass (broken-link check runs during
pnpm build).
File Structure
- Modify (docs worktree):
docs/acquisti/step.mdx— rewrite the "Selezione fornitori" toolbar + selection/contact prose; add the Aggiungi ai contatti paragraph.docs/faq.mdx— consistency check only (likely unchanged).static/img/screenshots/acquisti-lista-candidati.png,acquisti-candidati-selezione-free.png,acquisti-candidati-stati.png— re-captured (binary).
- Create (app repo
../factorybook):backend/database/seeders/DocsCandidatesSelectAllSeeder.php— RFQ in SELEZIONE FORNITORI with realistic candidates, for the demo account.
Task 1: Rewrite the "Selezione fornitori" toolbar + selection/contact prose in step.mdx
Files:
- Modify:
docs/acquisti/step.mdx(section "Selezione fornitori", ≈ lines 42–61, plus audit through line ~99)
Interfaces:
-
Consumes: existing screenshot references (unchanged filenames), existing
<StateLabel>usage, existing cross-link style/docs/.... -
Produces: accurate prose describing the two-row toolbar + per-card Aggiungi ai contatti (consumed by the reader; screenshots in Task 4 must match it).
-
Step 1: Read the current section
Run: open docs/acquisti/step.mdx and re-read lines 29–99 to anchor the edits.
- Step 2: Replace the "Sopra l'elenco si trovano" bullets (≈ lines 42–46)
Replace the current single-row bullet list with a two-row description. Use exactly this content (Italian):
Sopra la lista sono presenti due file di comandi.
La prima riga raccoglie le azioni per popolare l'elenco:
- **Aggiungi fornitori** — apre una finestra per aggiungere manualmente fornitori specifici, cercandoli per nome o scegliendoli da una lista di contatti;
- **Importa fornitori** — consente il caricamento in blocco di più fornitori;
- il box di **ricerca**, a destra, per filtrare i candidati per nome.
Quando è possibile ampliare l'elenco compare inoltre il riquadro **Ricerca automatica**, che avvia (o ripete) la ricerca automatica dei fornitori in base alla descrizione della richiesta e alle aree di lavoro.
La seconda riga gestisce selezione, filtri e contatto:
- **Seleziona tutti i candidati** — il pulsante seleziona in blocco tutti i candidati; una volta selezionati tutti, la stessa etichetta diventa **Cancella selezione** per azzerare la scelta;
- **Filtra:** — gli interruttori **Con quotazione** e **Con messaggi** restringono la lista ai soli fornitori che hanno interagito;
- **Contatta Fornitori** — il pulsante, a destra, invia la richiesta ai fornitori selezionati; resta disattivato finché non è selezionato almeno un candidato.
- Step 3: Rewrite the select/contact prose (the old ≈ line 61 sentence)
Ensure the prose after the plan subsection reflects the button (not a checkbox). Replace the "Una volta definita la selezione, premere CONTATTA FORNITORI…" sentence with:
Definita la selezione — in blocco con **Seleziona tutti i candidati**, oppure una alla volta con la checkbox sulla card (funzione dei piani Base e Premium) — premere **Contatta Fornitori** per inviare la richiesta ai candidati scelti. La selezione può essere rimandata e ripresa in un secondo momento.
- Step 4: Keep and reconcile "Selezione dei candidati e piani" (≈ lines 48–58)
Leave the plan-tier subsection and its Free alert quote as-is (verified still accurate). Only change the phrase "la checkbox Seleziona tutti" if it still appears, so it refers to the Seleziona tutti i candidati button. The Free-plan alert text and the "contatto gratuito" info admonition stay unchanged.
- Step 5: Add the "Aggiungi ai contatti" paragraph
After the contact prose (before the "Analisi delle offerte" heading), add:
:::tip[Salvare un fornitore tra i contatti]
Ogni card dispone del pulsante **Aggiungi ai contatti**, che salva il fornitore nella tua rubrica e nelle [liste di contatti](/docs/connessioni/liste), indipendentemente dal fatto che lo si contatti per questa richiesta. Una volta salvato, il pulsante mostra **Nei contatti**; la freccia accanto apre la finestra completa di gestione del contatto (tipo contatto, referente, note, liste). Per i dettagli vedi [Elenco Connessioni](/docs/connessioni/elenco).
:::
- Step 6: Audit the rest of the section
Skim lines ~63–99 ("Analisi delle offerte", "Feedback dai fornitori"). Confirm the filters mention (≈ line 83) is consistent with the toggles ("opzioni Con quotazione e Con messaggi" is fine). Fix any remaining "checkbox"/"a destra la checkbox Seleziona tutti" wording. Make no other content changes.
- Step 7: Build to verify MDX + links
Run (in the worktree): pnpm build
Expected: build completes; no MDX parse error; no "Docusaurus found broken links" for the new /docs/connessioni/liste and /docs/connessioni/elenco anchors.
- Step 8: Commit
git add docs/acquisti/step.mdx
git commit -m "docs(acquisti): document redesigned candidates toolbar & select-all (RIC-136)"
Task 2: FAQ consistency check
Files:
- Modify (only if needed):
docs/faq.mdx(≈ lines 106, 308)
Interfaces:
-
Consumes: the select-all/plan wording finalized in Task 1.
-
Produces: a FAQ consistent with
step.mdx. -
Step 1: Read the two FAQ passages
Run: read docs/faq.mdx around lines 100–110 and 305–312.
- Step 2: Compare against Task 1 wording
Both passages already say: bulk Seleziona tutti on all plans; single-supplier selection on Base/Premium. Confirm they still match step.mdx. If they contradict the rewritten section, make the minimal edit to align (keep the existing [Vai alla guida →](/docs/acquisti/step) link).
- Step 3: Build (only if a change was made)
Run: pnpm build
Expected: build passes.
- Step 4: Commit (only if a change was made)
git add docs/faq.mdx
git commit -m "docs(faq): align candidates selection wording with RIC-136"
If no change was needed, note "FAQ already consistent — no edit" and skip the commit.
Task 3: Seed a SELEZIONE FORNITORI candidates list for the demo account
Files:
- Create:
../factorybook/backend/database/seeders/DocsCandidatesSelectAllSeeder.php - Reference/template:
../factorybook/backend/database/seeders/Ric75CandidateStatesSeeder.php
Interfaces:
-
Consumes:
DemoUserSeeder(demo user + Tecnomec company), theQuotationRequest/QuotationCandidatefactories, and the CANDIDATE_SELECTION request-state class. -
Produces: one RFQ (
order_number = 'RIC136-DEMO') in SELEZIONE FORNITORI with ~6 verified, uncontacted candidates → the data Task 4 screenshots. -
Step 1: Confirm the CANDIDATE_SELECTION state class and demo seeder constants
Run (in ../factorybook):
grep -rn "class CandidateSelection" backend/app/States/QuotationRequest/ and
grep -n "USER_EMAIL\|COMPANY_NAME\|const " backend/database/seeders/DemoUserSeeder.php
Expected: a App\States\QuotationRequest\CandidateSelection class exists, and DemoUserSeeder exposes the demo email/company (or seeds [email protected] / Tecnomec S.r.l.). Use whichever accessor DemoUserSeeder provides to look up the user/company (mirror how Ric75CandidateStatesSeeder looks them up, but bound to DemoUserSeeder, not LocalTestUserSeeder).
- Step 2: Write the seeder
Create DocsCandidatesSelectAllSeeder.php, modeled on Ric75CandidateStatesSeeder but:
-
ORDER_NUMBER = 'RIC136-DEMO', subject e.g.'RIC-136 · Selezione fornitori'. -
Bootstraps via
DemoUserSeeder(call it if the demo user is missing), and resolves the demoUser+Companyfrom it. -
RFQ state:
App\States\QuotationRequest\CandidateSelection(SELEZIONE FORNITORI), so the Seleziona tutti i candidati button is enabled and no offers/badges are present. -
~6 verified, registered candidates with realistic Italian names + provinces and an
ai_motivation, all uncontacted (sent_at = null, no quotations, no messages, not preselected) so the list shows the clean pre-contact state. Realistic names, e.g.:Meccanica Alpina S.r.l.(Cuneo, CN),Ferrari e figli(Verona, VR),Officine Padane S.p.A.(Rovigo, RO),CarpenterIa Adriatica S.r.l.(Ancona, AN),Tornerie Lombarde S.r.l.(Brescia, BS),Precisione Emiliana S.r.l.(Modena, MO). (Fix the intentional typo — useCarpenteria Adriatica S.r.l.) -
Idempotent
cleanPreviousDemo()keyed onORDER_NUMBER(copy the pattern from the template). -
Print the RFQ uuid at the end.
-
Step 3: Run the seeder
Run (in ../factorybook/backend): php artisan db:seed --class=DocsCandidatesSelectAllSeeder
Expected: Seeded demo RFQ 'RIC136-DEMO' (<uuid>) for [email protected].
- Step 4: Verify idempotency
Run the same command again.
Expected: it succeeds again with a single RIC136-DEMO RFQ (no duplicate) — confirm with
php artisan tinker --execute="echo \App\Models\QuotationRequest::withTrashed()->where('order_number','RIC136-DEMO')->count();"
Expected output: 1.
- Step 5: Commit the seeder (in the app repo, on a safe branch)
The seeder lives in ../factorybook, not the docs branch. Do NOT commit it to the docs worktree. In ../factorybook, commit it on a non-default branch (or leave it staged for the maintainer per their preference):
cd /Users/ricventu/code/Factorybook/factorybook
git add backend/database/seeders/DocsCandidatesSelectAllSeeder.php
git commit -m "test(seeders): DocsCandidatesSelectAllSeeder for RIC-136 docs screenshots"
If committing to the app repo is out of scope for this session, note that the seeder was created + run and leave it for the maintainer.
Task 4: Re-capture the screenshots
Files:
- Modify (docs worktree, binary):
static/img/screenshots/acquisti-lista-candidati.png,static/img/screenshots/acquisti-candidati-selezione-free.png, and conditionallystatic/img/screenshots/acquisti-candidati-stati.png
Interfaces:
-
Consumes: the seeded
RIC136-DEMORFQ (Task 3) and, for the badges shot, theRIC75-DEMORFQ (existing seeder). -
Produces: updated PNGs matching the Task 1 prose.
-
Step 1: Boot the local stack
In ../factorybook: ensure minio is running, then start backend and webapp:
cd backend && php artisan serve --port=8000 and (separate shell) cd webapp && pnpm dev.
Confirm hosts app.factorybook.test / api.factorybook.test resolve to 127.0.0.1.
Expected: the app loads at http://app.factorybook.test.
- Step 2: Log in as the demo account (chrome-devtools MCP)
Set viewport to 1423×867 @2x. Navigate to /login, use the Password tab, log in as [email protected] / password.
Expected: dashboard loads for Tecnomec S.r.l.
- Step 3: Open the seeded RFQ candidates list
Navigate to Acquisti > Richieste di Quotazione, open RIC136-DEMO (SELEZIONE FORNITORI). Confirm the candidates list shows the redesigned toolbar (Aggiungi fornitori / Importa fornitori / search; then Seleziona tutti i candidati + Filtra: toggles + Contatta Fornitori) and cards with the Aggiungi ai contatti button.
- Step 4: Capture
acquisti-lista-candidati.png
Frame the toolbar + at least one full card (showing Aggiungi ai contatti). Save/overwrite to static/img/screenshots/acquisti-lista-candidati.png in the docs worktree.
Expected: PNG at 2× width (~2846 px wide), replacing the old file.
- Step 5: Capture
acquisti-candidati-selezione-free.png(Free plan)
Reproduce the Free-plan state (per-card checkbox gated + the plan alert visible). First check how the current file was produced: git log --oneline -- static/img/screenshots/acquisti-candidati-selezione-free.png and inspect any related seeder. If no dedicated mechanism exists, temporarily set the demo company's subscription to a Free/Presenza plan (via the app admin or php artisan tinker), capture, then restore the original plan.
Save/overwrite to static/img/screenshots/acquisti-candidati-selezione-free.png.
Expected: the shot shows the alert "Con il tuo piano puoi contattare tutti i fornitori candidati insieme…" and the select-all button.
- Step 6: Re-capture
acquisti-candidati-stati.pngonly if the toolbar is visible
Open the RIC75-DEMO RFQ (ANALISI OFFERTE, badge states — run php artisan db:seed --class=Ric75CandidateStatesSeeder if not present). If the redesigned toolbar appears above the badge cards in the framing, re-capture so it stays consistent; otherwise leave the file unchanged and note "badges shot unaffected".
Save/overwrite to static/img/screenshots/acquisti-candidati-stati.png if re-captured.
- Step 7: Verify the images changed
Run (in the worktree): git status --short static/img/screenshots/
Expected: the re-captured PNG(s) listed as modified. Spot-check one by opening it — the new toolbar must be visible.
- Step 8: Commit the screenshots
git add static/img/screenshots/acquisti-lista-candidati.png static/img/screenshots/acquisti-candidati-selezione-free.png
# add acquisti-candidati-stati.png only if re-captured
git commit -m "docs(acquisti): refresh candidates-list screenshots for RIC-136"
Task 5: Final verification
Files: none (verification only)
- Step 1: Clean build
Run (in the worktree): pnpm build
Expected: build succeeds; no broken links; no MDX errors.
- Step 2: Visual check
Run: pnpm start, open /docs/acquisti/step, scroll to "Selezione fornitori".
Expected: the prose matches the new toolbar; the Aggiungi ai contatti tip and cross-links render; the new screenshots display and are legible; the plan-tier subsection reads correctly.
- Step 3: Confirm success criteria (from the spec)
Verify each spec success criterion: two-row toolbar described; select-all/clear button; Filtra: toggles; Contatta Fornitori; per-card Aggiungi ai contatti with cross-links; plan-tier rules consistent between step.mdx and faq.mdx; screenshots current; no stale "checkbox" wording; build clean.
- Step 4: Report status
Summarize what changed (files, screenshots, seeder) and confirm all criteria met. The branch is ready for review.
Self-Review
- Spec coverage: Toolbar rewrite → Task 1; Aggiungi ai contatti mention + cross-links → Task 1 Step 5; plan-tier text preserved → Task 1 Step 4; FAQ check → Task 2; screenshots (3 files) → Task 4; demo data/seeder → Task 3; build/link verification → Tasks 1, 5. All spec sections mapped.
- Placeholder scan: No TBD/TODO; all doc prose is provided verbatim; screenshot/seeder steps give exact commands. The one investigative step (Free-plan mechanism, Task 4 Step 5) has a concrete fallback (temporarily set the subscription plan).
- Consistency: Screenshot filenames identical across Tasks 4 and the spec and existing
step.mdxreferences;ORDER_NUMBER = 'RIC136-DEMO'used consistently across Task 3 steps; UI labels match the Global Constraints verbatim list.