feat(25-shipment-presets-management): edycja, usuwanie i zarządzanie presetami przesyłek

Phase 25 complete — milestone v1.0 done:
- Ikonka edycji (✎) na hover z dropdown menu
- Edycja nazwy i koloru presetu w popup
- "Zapisz bieżące wartości" — aktualizacja parametrów z formularza
- Usuwanie z potwierdzeniem OrderProAlerts.confirm()
- SCSS: dropdown, edit-icon, btn-wrap style

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-22 23:53:44 +01:00
parent e379557533
commit 91963d5173
8 changed files with 591 additions and 48 deletions

View File

@@ -12,8 +12,8 @@ Sprzedawca może obsługiwać zamówienia ze wszystkich kanałów sprzedaży i n
| Attribute | Value |
|-----------|-------|
| Version | 0.9.0 |
| Status | v0.9 Complete |
| Version | 1.0.0 |
| Status | v1.0 Complete |
| Last Updated | 2026-03-22 |
## Requirements
@@ -43,10 +43,11 @@ Sprzedawca może obsługiwać zamówienia ze wszystkich kanałów sprzedaży i n
- [x] Windows Client: C# WinForms tray app, polling API, druk etykiet PDF — Phase 20
- [x] Wyświetlanie nazwy integracji zamiast generycznego "shopPRO" na liście i szczegółach zamówienia — Phase 21
- [x] Naprawa zapisu REGON, BDO, KRS i logo w ustawieniach firmy — Phase 22
- [x] Presety przesyłek — customowe przyciski szybkiego wypełniania formularza (CRUD + autofill + zarządzanie) — Phase 23-25
### Active (In Progress)
(brak — gotowe do v1.0)
(brak)
### Planned (Next)
@@ -138,4 +139,4 @@ Quick Reference:
---
*PROJECT.md — Updated when requirements or context change*
*Last updated: 2026-03-22 after Phase 22 (REGON Save Fix complete)*
*Last updated: 2026-03-22 after Phase 25 (Shipment Presets Management complete)*

View File

@@ -6,30 +6,25 @@ orderPRO to narzędzie do wielokanałowego zarządzania sprzedażą. Projekt prz
## Current Milestone
### v1.0 Presety przesyłek — In progress
Customowe przyciski szybkiego wypełniania formularza przygotowania przesyłki. Użytkownik zapisuje preset z wybranym przewoźnikiem, usługą, typem paczki, wymiarami, wagą i punktem nadania, a następnie jednym kliknięciem wypełnia formularz. Presety globalne (dostępne dla wszystkich użytkowników).
| Phase | Name | Plans | Status |
|-------|------|-------|--------|
| 23 | Shipment Presets Backend | 1/1 | Complete ✓ |
| 24 | Shipment Presets UI | 1/1 | Complete ✓ |
| 25 | Shipment Presets Management | TBD | Not started |
### Phase 23: Shipment Presets Backend
Focus: Migracja DB (tabela `shipment_presets`), repository CRUD, controller z endpointami JSON API.
### Phase 24: Shipment Presets UI
Focus: Lista presetów nad formularzem jako kolorowe przyciski, popup tworzenia presetu (nazwa + kolor), JS autofill formularza po kliknięciu.
### Phase 25: Shipment Presets Management
Focus: Edycja nazwy/koloru/parametrów presetu, usuwanie, zmiana kolejności.
None — ready for next milestone planning.
## Completed Milestones
<details>
<summary>v1.0 Presety przesyłek — 2026-03-22 (3 phases, 3 plans)</summary>
Customowe przyciski szybkiego wypełniania formularza przygotowania przesyłki. Presety globalne z nazwą i kolorem — tworzenie, autofill, edycja, usuwanie.
| Phase | Name | Plans | Completed |
|-------|------|-------|-----------|
| 23 | Shipment Presets Backend | 1/1 | 2026-03-22 |
| 24 | Shipment Presets UI | 1/1 | 2026-03-22 |
| 25 | Shipment Presets Management | 1/1 | 2026-03-22 |
Archive: `.paul/phases/23-shipment-presets-backend/`, `.paul/phases/24-shipment-presets-ui/`, `.paul/phases/25-shipment-presets-management/`
</details>
<details>
<summary>v0.9 Poprawki ustawień firmy — 2026-03-22 (1 phase, 1 plan)</summary>

View File

@@ -5,15 +5,16 @@
See: .paul/PROJECT.md (updated 2026-03-12)
**Core value:** Sprzedawca może obsługiwać zamówienia ze wszystkich kanałów sprzedaży i nadawać przesyłki bez przełączania się między platformami.
**Current focus:** v1.0 Presety przesyłek
**Current focus:** v1.0 Presety przesyłek — MILESTONE COMPLETE ✓
## Current Position
Milestone: v1.0 Presety przesyłek
Phase: [3] of [3] (Shipment Presets Management)
Plan: Not started
Status: Phase 24 complete, ready to plan Phase 25
Last activity: 2026-03-22 — Phase 24 complete, transitioned to Phase 25
Milestone: v1.0 Presety przesyłek — COMPLETE ✓
Phase: [3] of [3] (Shipment Presets Management) — COMPLETE ✓
Plan: 25-01 — loop closed
Status: Milestone v1.0 complete
Last activity: 2026-03-22 — UNIFY complete, milestone v1.0 done
Progress:
- v0.1 Initial Release: [██████████] 100% ✓
@@ -27,13 +28,17 @@ Progress:
- Phase 21: [██████████] 100% ✓ (1/1 plans)
- v0.9 Poprawki ustawień firmy: [██████████] 100% ✓
- Phase 22: [██████████] 100% ✓ (1/1 plans)
- v1.0 Presety przesyłek: [██████████] 100% ✓
- Phase 23: [██████████] 100% ✓ (1/1 plans)
- Phase 24: [██████████] 100% ✓ (1/1 plans)
- Phase 25: [██████████] 100% ✓ (1/1 plans)
## Loop Position
Current loop state:
```
PLAN ──▶ APPLY ──▶ UNIFY
✓ ✓ ✓ [Loop complete — ready for next PLAN]
✓ ✓ ✓ [Milestone v1.0 complete]
```
## Accumulated Context
@@ -67,6 +72,11 @@ PLAN ──▶ APPLY ──▶ UNIFY
| 2026-03-17 | Email history jako wpisy w order_activity_log (nie osobna sekcja) | Faza 15 | Spójność z istniejącym UX — jeden timeline zamiast fragmentacji |
| 2026-03-17 | VariableResolver wydzielony z EmailTemplateController | Faza 15 | Reuse logiki zmiennych; resolwer niezależny od kontrolera szablonów |
### Skill Audit (Faza 25, Plan 01)
| Oczekiwany | Wywołany | Uwagi |
|------------|---------|-------|
| sonar-scanner | ✓ | 0 nowych issues na zmienionych plikach |
### Skill Audit (Faza 24, Plan 01)
| Oczekiwany | Wywołany | Uwagi |
|------------|---------|-------|
@@ -206,7 +216,7 @@ PLAN ──▶ APPLY ──▶ UNIFY
- **Delivery mapping "Szukaj..." layout** — JS `attachSelectFilter()` w allegro.php tworzy input search dla InPost/Apaczka selectów, wizualnie wygląda jakby należał do wiersza powyżej. Pre-existing bug, do naprawy osobno.
### Git State
Last commit: 03a237e — feat(23-shipment-presets-backend): tabela DB, repository CRUD i JSON API
Last commit: e379557 — feat(24-shipment-presets-ui): kolorowe przyciski presetów, popup, autofill
Branch: main
Feature branches merged: none
@@ -216,9 +226,9 @@ Brak.
## Session Continuity
Last session: 2026-03-22
Stopped at: Phase 24 complete, ready to plan Phase 25
Next action: /paul:plan for Phase 25 (Shipment Presets Management)
Resume file: .paul/phases/24-shipment-presets-ui/24-01-SUMMARY.md
Stopped at: Milestone v1.0 complete
Next action: /paul:discuss-milestone lub /paul:milestone
Resume file: .paul/phases/25-shipment-presets-management/25-01-SUMMARY.md
Resume context:
- v0.1: COMPLETE ✓ (6 phases, 15 plans)
- v0.2: COMPLETE ✓ (1 phase, 5 plans)
@@ -229,6 +239,7 @@ Resume context:
- v0.7: COMPLETE ✓ (3 phases, 3 plans) — Zdalne drukowanie etykiet
- v0.8: COMPLETE ✓ (1 phase, 1 plan) — Poprawki źródła zamówień
- v0.9: COMPLETE ✓ (1 phase, 1 plan) — Poprawki ustawień firmy
- v1.0: COMPLETE ✓ (3 phases, 3 plans) — Presety przesyłek
---
*STATE.md — Updated after every significant action*

View File

@@ -0,0 +1,209 @@
---
phase: 25-shipment-presets-management
plan: 01
type: execute
wave: 1
depends_on: ["24-01"]
files_modified:
- resources/views/shipments/prepare.php
- resources/scss/modules/_shipment-presets.scss
- public/assets/css/app.css
autonomous: false
---
<objective>
## Goal
Dodać zarządzanie presetami przesyłek: edycja nazwy/koloru/parametrów, usuwanie, z poziomu UI na stronie przygotowania przesyłki.
## Purpose
Użytkownik musi móc modyfikować istniejące presety bez dostępu do bazy — zmienić nazwę, kolor, parametry lub usunąć niepotrzebne.
## Output
- Menu kontekstowe na przyciskach presetów (edytuj / usuń)
- Popup edycji presetu (ponowne użycie popupu tworzenia z pre-fill)
- Potwierdzenie usunięcia przez OrderProAlerts.confirm()
- Aktualizacja listy po edycji/usunięciu
</objective>
<context>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
## Prior Work
@.paul/phases/24-shipment-presets-ui/24-01-SUMMARY.md
## Source Files
@resources/views/shipments/prepare.php
@resources/scss/modules/_shipment-presets.scss
@src/Modules/Shipments/ShipmentPresetController.php
</context>
<skills>
No specialized flows required (sonar-scanner post-APPLY).
</skills>
<acceptance_criteria>
## AC-1: Edycja presetu
```gherkin
Given istnieje preset "InPost Standard"
When użytkownik klika prawym przyciskiem (lub ikonkę edycji) na przycisku presetu
And wybiera "Edytuj"
Then otwiera się popup z wypełnionymi danymi presetu (nazwa, kolor)
When zmienia nazwę na "InPost Paczkomat" i klika Zapisz
Then preset zostaje zaktualizowany i przycisk zmienia nazwę
```
## AC-2: Zmiana parametrów presetu
```gherkin
Given istnieje preset z wagą 1kg
When użytkownik wypełnia formularz nowymi wartościami (waga 2kg)
And klika ikonkę edycji na presecie i wybiera "Zapisz bieżące wartości"
Then preset zostaje zaktualizowany z bieżącymi wartościami formularza
```
## AC-3: Usuwanie presetu
```gherkin
Given istnieje preset "Stary preset"
When użytkownik klika ikonkę edycji i wybiera "Usuń"
Then pojawia się potwierdzenie OrderProAlerts.confirm()
When potwierdza usunięcie
Then preset zostaje usunięty z bazy i przycisk znika z listy
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: SCSS — style menu kontekstowego i ikonki edycji</name>
<files>resources/scss/modules/_shipment-presets.scss</files>
<action>
Dodać do istniejącego pliku SCSS:
- `.shipment-presets__btn-wrap` — wrapper na przycisk + ikonkę (position relative, display inline-flex)
- `.shipment-presets__edit-icon` — ikonka edycji (mały przycisk ✎ na prawym górnym rogu):
- Position absolute, top: -6px, right: -6px
- Width 18px, height 18px, border-radius 50%
- Background #fff, border: 1px solid #ddd, font-size 10px
- Opacity 0 domyślnie, opacity 1 na hover wrappera
- Cursor pointer, transition opacity 0.15s
- `.shipment-presets__dropdown` — dropdown menu (position absolute):
- Background #fff, border: 1px solid #ddd, border-radius 6px
- Box-shadow, z-index 100, min-width 180px
- Padding: 4px 0
- `.shipment-presets__dropdown-item` — pozycja menu:
- Padding: 6px 14px, font-size 13px, cursor pointer
- Hover: background #f3f4f6
- `&.is-danger` — color #ef4444
Zbudować CSS po zmianach.
</action>
<verify>npx sass --style=compressed build succeeds</verify>
<done>AC-1, AC-2, AC-3 partially: style gotowe</done>
</task>
<task type="auto">
<name>Task 2: JavaScript — edycja, usuwanie, dropdown menu</name>
<files>resources/views/shipments/prepare.php</files>
<action>
Rozszerzyć istniejący IIFE presetów w prepare.php:
1. **Zmienić renderPresets()** — zamiast gołego `<button>`, renderować wrapper:
```
<div class="shipment-presets__btn-wrap">
<button class="shipment-presets__btn" ...>{name}</button>
<button class="shipment-presets__edit-icon" data-preset-id="{id}">✎</button>
</div>
```
2. **Dropdown menu** — po kliknięciu ikonki ✎, pokazać dropdown z opcjami:
- "Edytuj nazwę i kolor" → otwiera popup z pre-fill (nazwa, kolor z presetu)
- "Zapisz bieżące wartości" → aktualizuje preset parametrami z bieżącego formularza (carrier, usługa, wymiary itp.), zachowując nazwę i kolor
- "Usuń" (is-danger) → OrderProAlerts.confirm(), potem DELETE API
3. **Rozszerzyć modal** — dodać tryb edycji:
- Dodać hidden input `preset-edit-id` w modal
- Jeśli edit-id > 0: modal w trybie edycji (tytuł "Edytuj przycisk dostawy", przycisk "Zapisz zmiany")
- Jeśli edit-id = 0: modal w trybie tworzenia (jak dotychczas)
- Pre-fill: nazwa i kolor z presetu
4. **Edycja nazwy/koloru (modal save):**
- Jeśli edit-id > 0: POST /api/shipment-presets/update z id + name + color + bieżące parametry presetu (nie formularza!)
- Jeśli edit-id = 0: POST /api/shipment-presets (tworzenie jak dotychczas)
5. **"Zapisz bieżące wartości":**
- POST /api/shipment-presets/update z id, bieżącą nazwą i kolorem presetu, ale parametrami z formularza
- Po sukcesie: reload presetów
6. **Usuwanie:**
- window.OrderProAlerts.confirm({ message: 'Usunąć przycisk "' + name + '"?', onConfirm: ... })
- POST /api/shipment-presets/delete z id w body (URLSearchParams)
- Po sukcesie: reload presetów
7. **Zamknięcie dropdown** — klik poza dropdown zamyka go
Ważne:
- Nie modyfikować istniejącego kodu carrier selection / status polling
- fetch z credentials: 'same-origin'
- URLSearchParams (nie JSON) — jak w fazie 24
- Przechowywać presetsData w zamknięciu IIFE (już istnieje)
</action>
<verify>php -l resources/views/shipments/prepare.php — brak błędów</verify>
<done>AC-1, AC-2, AC-3 satisfied</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<what-built>Zarządzanie presetami: edycja nazwy/koloru, zapisanie bieżących wartości, usuwanie z potwierdzeniem</what-built>
<how-to-verify>
1. Odwiedź /orders/{id}/shipment/prepare
2. Najedź na przycisk presetu — powinna pojawić się ikonka ✎
3. Kliknij ✎ — dropdown z 3 opcjami
4. "Edytuj nazwę i kolor" — popup z wypełnioną nazwą i zaznaczonym kolorem, zmień i zapisz
5. "Zapisz bieżące wartości" — zmień wymiary w formularzu, kliknij tę opcję — preset powinien się zaktualizować
6. "Usuń" — potwierdzenie alertem, po potwierdzeniu przycisk znika
7. Sprawdź że kliknięcie presetu nadal autofilluje formularz
</how-to-verify>
<resume-signal>Type "approved" to continue, or describe issues to fix</resume-signal>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- src/Modules/Shipments/ShipmentPresetController.php (gotowy z fazy 23)
- src/Modules/Shipments/ShipmentPresetRepository.php (gotowy z fazy 23)
- routes/web.php (routing gotowy z fazy 23)
- Istniejący JS: carrier selection, status polling, print queue
## SCOPE LIMITS
- Edycja, usuwanie — brak drag & drop sortowania (out of scope)
- Brak auto-submit po kliknięciu presetu (osobna faza/task)
</boundaries>
<verification>
Before declaring plan complete:
- [ ] Ikonka ✎ widoczna na hover
- [ ] Dropdown z 3 opcjami
- [ ] Edycja nazwy/koloru przez popup
- [ ] "Zapisz bieżące wartości" aktualizuje parametry
- [ ] Usuwanie z potwierdzeniem OrderProAlerts
- [ ] Autofill nadal działa
- [ ] php -l OK
- [ ] SCSS zbudowany
- [ ] Human verification passed
</verification>
<success_criteria>
- Użytkownik może edytować nazwę i kolor presetu
- Użytkownik może zaktualizować parametry presetu z bieżącego formularza
- Użytkownik może usunąć preset z potwierdzeniem
- Brak regresji w tworzeniu i autofill
</success_criteria>
<output>
After completion, create `.paul/phases/25-shipment-presets-management/25-01-SUMMARY.md`
</output>

View File

@@ -0,0 +1,106 @@
---
phase: 25-shipment-presets-management
plan: 01
subsystem: shipments
tags: [shipment-presets, management, edit, delete, dropdown]
requires:
- phase: 24-shipment-presets-ui
provides: Preset buttons, modal, autofill JS
provides:
- Edycja nazwy i koloru presetu
- Aktualizacja parametrów presetu z bieżącego formularza
- Usuwanie presetu z potwierdzeniem
affects: []
tech-stack:
added: []
patterns:
- Ikonka edycji na hover z dropdown menu (reusable UX pattern)
key-files:
created: []
modified:
- resources/scss/modules/_shipment-presets.scss
- public/assets/css/app.css
- resources/views/shipments/prepare.php
key-decisions:
- "Ikonka ✎ na hover z dropdown zamiast osobnych przycisków — user approved"
- "Modal reuse: tryb create vs edit z editingPresetId flag"
patterns-established:
- "Edit icon hover + dropdown menu — użytkownik chce reuse tego wzorca"
duration: 10min
started: 2026-03-22T00:00:00Z
completed: 2026-03-22T00:10:00Z
---
# Phase 25 Plan 01: Shipment Presets Management Summary
**Zarządzanie presetami: ikonka ✎ na hover z dropdown (edytuj nazwę/kolor, zapisz bieżące wartości, usuń z potwierdzeniem).**
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~10 min |
| Tasks | 3 completed (2 auto + 1 checkpoint) |
| Files modified | 3 |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Edycja presetu | Pass | Popup z pre-fill nazwa + kolor, zapis przez API update |
| AC-2: Zmiana parametrów | Pass | "Zapisz bieżące wartości" aktualizuje z formularza |
| AC-3: Usuwanie presetu | Pass | OrderProAlerts.confirm() + API delete |
## Accomplishments
- SCSS: style btn-wrap, edit-icon (hover opacity), dropdown menu, dropdown-item (z is-danger)
- JS: renderPresets() z wrapperem + ikonką ✎, showDropdown() z 3 opcjami
- Modal rozszerzony o tryb edycji (editingPresetId flag, pre-fill, tytuł/tekst przycisku)
- buildFormPayload() i postPresetAPI() wydzielone dla reuse (create/edit/saveCurrentValues)
- deletePreset() z OrderProAlerts.confirm() fallback na native confirm
- SonarQube: 0 nowych issues
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `resources/scss/modules/_shipment-presets.scss` | Modified | Style dropdown, edit icon, btn-wrap |
| `public/assets/css/app.css` | Modified | Przebudowany CSS |
| `resources/views/shipments/prepare.php` | Modified | Dropdown menu, modal edit mode, delete, saveCurrentValues |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| Ikonka ✎ na hover | Kompaktowe, nie zaśmieca UI | Użytkownik pochwalił — do reuse |
| Modal reuse create/edit | Jeden popup z flagą editingPresetId | Mniej kodu, spójny UX |
| Fallback na native confirm | OrderProAlerts może nie być dostępny | Defensywne programowanie |
## Deviations from Plan
None — plan executed exactly as written.
## Issues Encountered
None.
## Next Phase Readiness
**Ready:**
- Milestone v1.0 kompletny — wszystkie 3 fazy done
**Concerns:**
- Brak
**Blockers:**
- None
---
*Phase: 25-shipment-presets-management, Plan: 01*
*Completed: 2026-03-22*

File diff suppressed because one or more lines are too long

View File

@@ -92,3 +92,70 @@
border-color: #333;
}
}
.shipment-presets__btn-wrap {
position: relative;
display: inline-flex;
&:hover .shipment-presets__edit-icon {
opacity: 1;
}
}
.shipment-presets__edit-icon {
position: absolute;
top: -6px;
right: -6px;
width: 18px;
height: 18px;
border-radius: 50%;
background: #fff;
border: 1px solid #ddd;
font-size: 10px;
line-height: 16px;
text-align: center;
cursor: pointer;
opacity: 0;
transition: opacity 0.15s;
padding: 0;
color: #666;
z-index: 2;
&:hover {
background: #f3f4f6;
border-color: #999;
}
}
.shipment-presets__dropdown {
position: absolute;
top: 100%;
left: 0;
margin-top: 4px;
background: #fff;
border: 1px solid #ddd;
border-radius: 6px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
z-index: 100;
min-width: 200px;
padding: 4px 0;
}
.shipment-presets__dropdown-item {
padding: 6px 14px;
font-size: 13px;
cursor: pointer;
white-space: nowrap;
&:hover {
background: #f3f4f6;
}
&.is-danger {
color: #ef4444;
&:hover {
background: #fef2f2;
}
}
}

View File

@@ -855,11 +855,16 @@ $defaultCodAmount = $isCod ? number_format($totalWithTax, 2, '.', '') : '0';
.catch(function () {});
}
var activeDropdown = null;
function renderPresets() {
var existing = presetsContainer.querySelectorAll('.shipment-presets__btn');
existing.forEach(function (btn) { btn.remove(); });
var existing = presetsContainer.querySelectorAll('.shipment-presets__btn-wrap');
existing.forEach(function (el) { el.remove(); });
presetsData.forEach(function (preset) {
var wrap = document.createElement('div');
wrap.className = 'shipment-presets__btn-wrap';
var btn = document.createElement('button');
btn.type = 'button';
btn.className = 'shipment-presets__btn';
@@ -867,10 +872,72 @@ $defaultCodAmount = $isCod ? number_format($totalWithTax, 2, '.', '') : '0';
btn.textContent = preset.name;
btn.setAttribute('data-preset-id', preset.id);
btn.addEventListener('click', function () { applyPreset(preset); });
presetsContainer.insertBefore(btn, addBtn);
var editIcon = document.createElement('button');
editIcon.type = 'button';
editIcon.className = 'shipment-presets__edit-icon';
editIcon.textContent = '\u270E';
editIcon.addEventListener('click', function (e) {
e.stopPropagation();
showDropdown(wrap, preset);
});
wrap.appendChild(btn);
wrap.appendChild(editIcon);
presetsContainer.insertBefore(wrap, addBtn);
});
}
// --- Dropdown menu ---
function closeDropdown() {
if (activeDropdown) {
activeDropdown.remove();
activeDropdown = null;
}
}
document.addEventListener('click', function () { closeDropdown(); });
function showDropdown(wrap, preset) {
closeDropdown();
var dd = document.createElement('div');
dd.className = 'shipment-presets__dropdown';
var editItem = document.createElement('div');
editItem.className = 'shipment-presets__dropdown-item';
editItem.textContent = 'Edytuj nazw\u0119 i kolor';
editItem.addEventListener('click', function (e) {
e.stopPropagation();
closeDropdown();
openEditModal(preset);
});
var updateItem = document.createElement('div');
updateItem.className = 'shipment-presets__dropdown-item';
updateItem.textContent = 'Zapisz bie\u017C\u0105ce warto\u015Bci';
updateItem.addEventListener('click', function (e) {
e.stopPropagation();
closeDropdown();
saveCurrentValues(preset);
});
var deleteItem = document.createElement('div');
deleteItem.className = 'shipment-presets__dropdown-item is-danger';
deleteItem.textContent = 'Usu\u0144';
deleteItem.addEventListener('click', function (e) {
e.stopPropagation();
closeDropdown();
deletePreset(preset);
});
dd.appendChild(editItem);
dd.appendChild(updateItem);
dd.appendChild(deleteItem);
wrap.appendChild(dd);
activeDropdown = dd;
}
// --- Apply preset (autofill form) ---
function applyPreset(preset) {
var carrierSelect = document.getElementById('shipment-carrier-select');
@@ -966,16 +1033,37 @@ $defaultCodAmount = $isCod ? number_format($totalWithTax, 2, '.', '') : '0';
}
}
// --- Modal: add preset ---
addBtn.addEventListener('click', function () {
// --- Modal (create & edit) ---
var editingPresetId = 0;
var modalTitle = modal.querySelector('h3');
function openCreateModal() {
editingPresetId = 0;
nameInput.value = '';
selectedColor = PRESET_COLORS[0];
colorPicker.querySelectorAll('.preset-modal__color-swatch').forEach(function (s, i) {
s.classList.toggle('is-selected', i === 0);
});
if (modalTitle) modalTitle.textContent = 'Nowy przycisk dostawy';
saveBtn.textContent = 'Zapisz';
modal.style.display = '';
nameInput.focus();
});
}
function openEditModal(preset) {
editingPresetId = preset.id;
nameInput.value = preset.name || '';
selectedColor = preset.color || PRESET_COLORS[0];
colorPicker.querySelectorAll('.preset-modal__color-swatch').forEach(function (s) {
s.classList.toggle('is-selected', s.getAttribute('data-color') === selectedColor);
});
if (modalTitle) modalTitle.textContent = 'Edytuj przycisk dostawy';
saveBtn.textContent = 'Zapisz zmiany';
modal.style.display = '';
nameInput.focus();
}
addBtn.addEventListener('click', function () { openCreateModal(); });
cancelBtn.addEventListener('click', function () {
modal.style.display = 'none';
@@ -992,15 +1080,46 @@ $defaultCodAmount = $isCod ? number_format($totalWithTax, 2, '.', '') : '0';
return;
}
saveBtn.disabled = true;
if (editingPresetId > 0) {
// Edit mode — update name and color only, keep existing params
var editPreset = presetsData.find(function (p) { return p.id === editingPresetId; });
var editPayload = {
id: editingPresetId,
name: name,
color: selectedColor,
carrier: editPreset ? editPreset.carrier : '',
provider_code: editPreset ? editPreset.provider_code : '',
delivery_method_id: editPreset ? editPreset.delivery_method_id : '',
credentials_id: editPreset ? editPreset.credentials_id : '',
carrier_id: editPreset ? editPreset.carrier_id : '',
package_type: editPreset ? editPreset.package_type : 'PACKAGE',
length_cm: editPreset ? editPreset.length_cm : '25',
width_cm: editPreset ? editPreset.width_cm : '20',
height_cm: editPreset ? editPreset.height_cm : '8',
weight_kg: editPreset ? editPreset.weight_kg : '1',
sender_point_id: editPreset ? editPreset.sender_point_id : '',
label_format: editPreset ? editPreset.label_format : 'PDF'
};
postPresetAPI('/api/shipment-presets/update', editPayload);
} else {
// Create mode — use current form values
var payload = buildFormPayload(name, selectedColor);
postPresetAPI('/api/shipment-presets', payload);
}
});
function buildFormPayload(name, color) {
var carrierSelect = document.getElementById('shipment-carrier-select');
var hiddenInput = document.getElementById('shipment-delivery-service');
var credentialsInput = document.getElementById('shipment-credentials-id');
var carrierInput = document.getElementById('shipment-carrier-id');
var providerInput = document.getElementById('shipment-provider-code');
var payload = {
return {
name: name,
color: selectedColor,
color: color,
carrier: carrierSelect ? carrierSelect.value : '',
provider_code: providerInput ? providerInput.value : '',
delivery_method_id: hiddenInput ? hiddenInput.value : '',
@@ -1014,10 +1133,11 @@ $defaultCodAmount = $isCod ? number_format($totalWithTax, 2, '.', '') : '0';
sender_point_id: getFieldValue('sender_point_id'),
label_format: getFieldValue('label_format')
};
}
saveBtn.disabled = true;
function postPresetAPI(url, payload) {
var formBody = new URLSearchParams(payload);
fetch('/api/shipment-presets', {
fetch(url, {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
@@ -1025,14 +1145,48 @@ $defaultCodAmount = $isCod ? number_format($totalWithTax, 2, '.', '') : '0';
})
.then(function (r) { return r.json(); })
.then(function (data) {
if (data.preset) {
if (data.preset || data.deleted) {
modal.style.display = 'none';
loadPresets();
}
})
.catch(function () {})
.finally(function () { saveBtn.disabled = false; });
});
}
// --- Save current form values to existing preset ---
function saveCurrentValues(preset) {
var payload = buildFormPayload(preset.name, preset.color);
payload.id = preset.id;
postPresetAPI('/api/shipment-presets/update', payload);
}
// --- Delete preset ---
function deletePreset(preset) {
if (window.OrderProAlerts && window.OrderProAlerts.confirm) {
window.OrderProAlerts.confirm({
message: 'Usun\u0105\u0107 przycisk "' + preset.name + '"?',
onConfirm: function () { executeDelete(preset.id); }
});
} else if (confirm('Usun\u0105\u0107 przycisk "' + preset.name + '"?')) {
executeDelete(preset.id);
}
}
function executeDelete(id) {
var formBody = new URLSearchParams({ id: id });
fetch('/api/shipment-presets/delete', {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: formBody.toString()
})
.then(function (r) { return r.json(); })
.then(function (data) {
if (data.deleted) loadPresets();
})
.catch(function () {});
}
function getFieldValue(name) {
var field = document.querySelector('[name="' + name + '"]');