From fa01951d2765aa6c91fef8362d71a8cb4b33eaf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=BC=D0=B8=D1=82=D1=80=D0=B8=D0=B9?= Date: Thu, 14 May 2026 14:21:07 +0300 Subject: [PATCH] feat(pdd): render project name/limit/days form fields --- .../projects/ProjectDetailsDrawer.vue | 110 +++++++++++++++++- .../Frontend/ProjectDetailsDrawer.spec.ts | 32 +++++ 2 files changed, 140 insertions(+), 2 deletions(-) diff --git a/app/resources/js/components/projects/ProjectDetailsDrawer.vue b/app/resources/js/components/projects/ProjectDetailsDrawer.vue index ee62da50..1c653433 100644 --- a/app/resources/js/components/projects/ProjectDetailsDrawer.vue +++ b/app/resources/js/components/projects/ProjectDetailsDrawer.vue @@ -1,14 +1,104 @@ @@ -26,4 +116,20 @@ defineEmits<{ close: []; saved: [] }>(); z-index: 5; } .project-details-drawer.open { transform: translateX(0); } +.pdd-content { display: flex; flex-direction: column; height: 100%; } +.pdd-head { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid var(--liderra-line, #e6e2d6); } +.pdd-title { font-weight: 600; font-size: 16px; } +.pdd-close { background: none; border: 0; cursor: pointer; font-size: 18px; padding: 4px; } +.pdd-body { padding: 16px 20px; display: flex; flex-direction: column; gap: 14px; flex: 1; overflow-y: auto; } +.pdd-field { display: flex; flex-direction: column; gap: 4px; } +.pdd-label { font-size: 12px; color: #6b6f72; } +.pdd-input { padding: 8px 10px; border: 1px solid var(--liderra-line, #e6e2d6); border-radius: 6px; font: inherit; } +.pdd-days { display: flex; gap: 4px; } +.pdd-day { padding: 6px 10px; border: 1px solid var(--liderra-line, #e6e2d6); background: #ffffff; border-radius: 4px; cursor: pointer; font: inherit; } +.pdd-day.active { background: #0f6e56; color: #ffffff; border-color: #0f6e56; } +.pdd-foot { display: flex; justify-content: space-between; padding: 12px 20px; border-top: 1px solid var(--liderra-line, #e6e2d6); } +.pdd-foot-left, .pdd-foot-right { display: flex; gap: 8px; } +.pdd-btn { padding: 6px 14px; border: 0; border-radius: 6px; cursor: pointer; font: inherit; } +.pdd-btn-text { background: transparent; color: #081319; } +.pdd-btn-primary { background: #0f6e56; color: #ffffff; } diff --git a/app/tests/Frontend/ProjectDetailsDrawer.spec.ts b/app/tests/Frontend/ProjectDetailsDrawer.spec.ts index 41076471..067dcff5 100644 --- a/app/tests/Frontend/ProjectDetailsDrawer.spec.ts +++ b/app/tests/Frontend/ProjectDetailsDrawer.spec.ts @@ -2,6 +2,22 @@ import { describe, it, expect, beforeEach } from 'vitest'; import { mount } from '@vue/test-utils'; import { createPinia, setActivePinia } from 'pinia'; import ProjectDetailsDrawer from '../../resources/js/components/projects/ProjectDetailsDrawer.vue'; +import type { Project } from '../../resources/js/stores/projectsStore'; + +const sampleProject: Project = { + id: 42, + name: 'Натяжные потолки', + signal_type: 'call', + signal_identifier: '79161112233', + daily_limit_target: 30, + delivered_today: 0, + is_active: true, + archived_at: null, + region_mask: 0, + region_mode: 'include', + delivery_days_mask: 31, // Mon-Fri + sync_status: 'pending', +}; describe('ProjectDetailsDrawer', () => { beforeEach(() => setActivePinia(createPinia())); @@ -12,4 +28,20 @@ describe('ProjectDetailsDrawer', () => { expect(aside.exists()).toBe(true); expect(aside.classes()).not.toContain('open'); }); + + it('renders project name + daily_limit_target + delivery_days', () => { + const wrapper = mount(ProjectDetailsDrawer, { props: { project: sampleProject } }); + const aside = wrapper.find('aside.project-details-drawer'); + expect(aside.classes()).toContain('open'); + expect(wrapper.text()).toContain('Натяжные потолки'); + const nameInput = wrapper.get('input[data-testid="pdd-name"]'); + expect((nameInput.element as HTMLInputElement).value).toBe('Натяжные потолки'); + const limitInput = wrapper.get('input[data-testid="pdd-limit"]'); + expect((limitInput.element as HTMLInputElement).value).toBe('30'); + // Days mask 31 = bits 0..4 = Mon..Fri (5 days active) + const dayBtns = wrapper.findAll('button[data-testid^="pdd-day-"]'); + expect(dayBtns.length).toBe(7); + const activeBtns = dayBtns.filter(b => b.classes().includes('active')); + expect(activeBtns.length).toBe(5); + }); });