Files
orderPRO/resources/scss/modules/_order-notes.scss
Jacek Pyziak 48351b5f36 feat(129): order user notes module
CRUD notatek autorskich operatora per zamowienie z badge [N] na liscie
zamowien. Reuse istniejacej tabeli `order_notes` przez nowy
`note_type='user'` z `user_id` (FK->users SET NULL) i `author_name`
(snapshot). Sekcja `#notes` w "Wiadomosci i zalaczniki" w
`/orders/{id}` z inline edit form + delete przez
`OrderProAlerts.confirm`. Autoryzacja DB-level
(`WHERE user_id = :user_id`, rowCount=0 ⇒ 403) — bez admin override
(brak systemu rol w aplikacji).

- Migracja `20260514_000116_*.sql` (ADD COLUMN user_id + author_name +
  FK + indeks `idx_order_notes_type_order`); idempotentne z DDL
  no-op fallback.
- `OrderNotesService` (CRUD + walidacja body ≤ 2000 znakow); subquery
  `user_notes_count` w paginate; badge HTML w `toTableRow()`.
- 3 routy POST /orders/{id}/notes(/update|/delete).
- SCSS module `_order-notes.scss` + vanilla JS `order-notes.js`
  (inline edit toggle + delete confirm; idempotent guard).
- 9 kluczy i18n PL; PROJECT.md + ROADMAP.md + tech_changelog.md +
  db_schema.md zaktualizowane.

Follow-up: `php bin/migrate.php` + manualny smoke test (autor vs inny
user + badge na /orders/list).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 15:20:05 +02:00

113 lines
1.8 KiB
SCSS

// Phase 129-01: notatki autorskie operatora w szczegolach zamowienia + badge na liscie.
.order-notes-badge {
display: inline-block;
margin-left: 6px;
padding: 1px 6px;
border-radius: 10px;
background: #eef2ff;
color: #4338ca;
font-size: 11px;
font-weight: 600;
line-height: 1.4;
text-decoration: none;
vertical-align: middle;
transition: background 0.15s ease;
&:hover {
background: #e0e7ff;
text-decoration: none;
}
}
.order-notes-subtitle {
margin: 0 0 6px;
font-size: 12px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--c-muted, #64748b);
}
.order-user-notes {
display: flex;
flex-direction: column;
gap: 8px;
.order-event--user {
border-left: 3px solid #6366f1;
padding-left: 8px;
}
.order-event__head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
flex-wrap: wrap;
}
.order-event__meta {
font-size: 11px;
color: var(--c-muted, #64748b);
}
.order-event__actions {
display: inline-flex;
align-items: center;
gap: 8px;
}
}
.order-imported-notes {
.order-event--imported {
opacity: 0.75;
font-size: 12px;
}
}
.btn-link {
background: none;
border: 0;
padding: 0;
margin: 0;
font-size: 11px;
color: var(--c-primary, #2563eb);
cursor: pointer;
text-decoration: underline;
&:hover {
text-decoration: none;
}
&--danger {
color: #dc2626;
}
}
.order-note-form,
.order-note-edit-form {
textarea {
width: 100%;
min-height: 60px;
resize: vertical;
}
.order-note-form__actions,
.order-note-edit-form__actions {
display: flex;
gap: 8px;
margin-top: 6px;
}
}
.order-note-edit-form {
margin-top: 6px;
.order-note-edit-form__actions {
display: flex;
gap: 8px;
margin-top: 6px;
}
}