# πŸ“š ДокумСнтация ΠΏΠΎ Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³Ρƒ HomePage.vue ## 🎯 ΠžΠ±Π·ΠΎΡ€ HomePage.vue - Π³Π»Π°Π²Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ прилоТСния для управлСния ΠΈΠ³Ρ€ΠΎΠ²Ρ‹ΠΌ Ρ‚ΠΈΡ€ΠΎΠΌ. ΠŸΡ€ΠΎΡˆΠ΅Π» ΠΏΠΎΠ»Π½Ρ‹ΠΉ Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³ ΠΎΡ‚ ΠΌΠΎΠ½ΠΎΠ»ΠΈΡ‚Π½ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° (2456 строк) Π΄ΠΎ ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½ΠΎΠΉ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ Π½Π° Vue 3 Composition API. ## πŸ“Š ΠœΠ΅Ρ‚Ρ€ΠΈΠΊΠΈ Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³Π° | ΠœΠ΅Ρ‚Ρ€ΠΈΠΊΠ° | Π”ΠΎ Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³Π° | ПослС Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³Π° | Π£Π»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΠ΅ | |---------|----------------|-------------------|-----------| | **Π Π°Π·ΠΌΠ΅Ρ€ Ρ„Π°ΠΉΠ»Π°** | 2456 строк | ~600 строк | **-75%** | | **АрхитСктура** | ΠœΠΎΠ½ΠΎΠ»ΠΈΡ‚ | ΠœΠΎΠ΄ΡƒΠ»ΡŒΠ½Π°Ρ | βœ… | | **ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΠΎΡΡ‚ΡŒ** | БлоТная | ЛСгкая | βœ… | | **Π’Π΅ΡΡ‚ΠΈΡ€ΡƒΠ΅ΠΌΠΎΡΡ‚ΡŒ** | Низкая | Высокая | βœ… | | **ΠŸΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΠ΅** | ΠžΡ‚ΡΡƒΡ‚ΡΡ‚Π²ΡƒΠ΅Ρ‚ | МаксимальноС | βœ… | ## πŸ—οΈ Новая Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° ### Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ``` HomePage.vue (Π³Π»Π°Π²Π½Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚, ~600 строк) β”œβ”€β”€ Layout ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ β”‚ β”œβ”€β”€ AppHeader.vue β”‚ β”œβ”€β”€ AppMain.vue β”‚ └── AppFooter.vue β”œβ”€β”€ UI ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ β”‚ β”œβ”€β”€ IconButton.vue β”‚ β”œβ”€β”€ PlayPauseButton.vue β”‚ β”œβ”€β”€ ConfirmDialog.vue β”‚ β”œβ”€β”€ ThemeToggle.vue β”‚ β”œβ”€β”€ BurgerMenu.vue β”‚ └── TimeSemicircle.vue β”œβ”€β”€ Π˜Π³Ρ€ΠΎΠ²Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ β”‚ β”œβ”€β”€ GamePorts.vue β”‚ └── GamePort.vue └── ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ смСн β”œβ”€β”€ ShiftModal.vue β”œβ”€β”€ ShiftCloseModal.vue └── ShiftForm/ β”œβ”€β”€ FinancialSection.vue β”œβ”€β”€ ToysSection.vue └── SalarySection.vue ``` ### Composables architecture ``` composables/ β”œβ”€β”€ useAuth.js // АутСнтификация ΠΈ авторизация β”œβ”€β”€ game/ β”‚ β”œβ”€β”€ useGamePorts.js // Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΈΠ³Ρ€ΠΎΠ²Ρ‹ΠΌΠΈ ΠΏΠΎΡ€Ρ‚Π°ΠΌΠΈ β”‚ β”œβ”€β”€ useGameControl.js // ΠŸΠ°ΡƒΠ·Π°/воспроизвСдСниС β”‚ └── useTime.js // Π Π°Π±ΠΎΡ‚Π° со Π²Ρ€Π΅ΠΌΠ΅Π½Π΅ΠΌ β”œβ”€β”€ shift/ β”‚ β”œβ”€β”€ useShifts.js // Бтатус смСн β”‚ β”œβ”€β”€ useShiftOperations.js // ΠžΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ со смСнами β”‚ └── useShiftForm.js // Валидация Ρ„ΠΎΡ€ΠΌ смСн └── ui/ β”œβ”€β”€ useModals.js // Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΌΠΎΠ΄Π°Π»ΡŒΠ½Ρ‹ΠΌΠΈ ΠΎΠΊΠ½Π°ΠΌΠΈ β”œβ”€β”€ useConfirm.js // Π”ΠΈΠ°Π»ΠΎΠ³ΠΈ подтвСрТдСния └── useBurgerMenu.js // Π‘ΡƒΡ€Π³Π΅Ρ€ мСню ``` ## πŸ”§ ВСхничСскиС Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ### 1. Composition API с ` ``` ### 2. Π Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ отвСтствСнности **HomePage.vue Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π·Π°:** - ΠšΠΎΠΌΠΏΠΎΠ½ΠΎΠ²ΠΊΡƒ layout - ΠšΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ†ΠΈΡŽ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ - ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ основных событий - Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΌ состояниСм **Π›ΠΎΠ³ΠΈΠΊΠ° вынСсСна Π²:** - Composables для бизнСс-Π»ΠΎΠ³ΠΈΠΊΠΈ - ΠžΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ для UI - БСрвисы для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с API ### 3. Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ состояниСм **Π“Π»ΠΎΠ±Π°Π»ΡŒΠ½ΠΎΠ΅ состояниС:** ```javascript // useAuth.js - состояниС Π°ΡƒΡ‚Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ const user = ref(null) const isAuthenticated = computed(() => !!user.value) // useShiftOperations.js - состояниС смСн const shiftStatus = ref({ regularShift: null, techShift: null }) // useModals.js - состояниС ΠΌΠΎΠ΄Π°Π»ΡŒΠ½Ρ‹Ρ… ΠΎΠΊΠΎΠ½ const showShiftModal = ref(false) const showCloseShiftModal = ref(false) ``` **Π›ΠΎΠΊΠ°Π»ΡŒΠ½ΠΎΠ΅ состояниС:** ```javascript // HomePage.vue - Ρ‚ΠΎΠ»ΡŒΠΊΠΎ спСцифичноС для страницы состояниС const isPaused = ref(false) const closeShiftForm = ref({ money_konv: 0, money_razm_closed: 0, toys: [0, 0, 0, 0, 0] }) ``` ### 4. ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π½Π°Ρ систСма **UI ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ - ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Π΅:** ```vue ``` **БизнСс-ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ - ΠΏΡ€Π΅Π΄ΠΌΠ΅Ρ‚Π½ΠΎ-ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅:** ```vue ``` ## πŸš€ ΠŸΡ€Π΅ΠΈΠΌΡƒΡ‰Π΅ΡΡ‚Π²Π° Π½ΠΎΠ²ΠΎΠΉ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρ‹ ### 1. ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΠΎΡΡ‚ΡŒ - **ЧСткая структура** - ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ„Π°ΠΉΠ» ΠΈΠΌΠ΅Π΅Ρ‚ свою Π·ΠΎΠ½Ρƒ отвСтствСнности - **ЛСгкая навигация** - Π»ΠΎΠ³ΠΈΠΊΠ° сгруппирована ΠΏΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ - **Π‘Π°ΠΌΠΎΠ΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ ΠΊΠΎΠ΄** - названия composables ΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² говорят ΠΎ ΠΈΡ… Π½Π°Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΈ ### 2. Π’Π΅ΡΡ‚ΠΈΡ€ΡƒΠ΅ΠΌΠΎΡΡ‚ΡŒ - **Π˜Π·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Π΅Π΄ΠΈΠ½ΠΈΡ†Ρ‹** - ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ composable ΠΌΠΎΠΆΠ½ΠΎ Ρ‚Π΅ΡΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ - **Моки ΠΈ Π·Π°Π³Π»ΡƒΡˆΠΊΠΈ** - лСгкая ΠΏΠΎΠ΄ΠΌΠ΅Π½Π° зависимостСй - **ΠŸΠΎΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ ΠΊΠΎΠ΄Π°** - ΠΌΠΎΠΆΠ½ΠΎ Ρ‚Π΅ΡΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ### 3. ΠŸΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ - **UI ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹** - ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π²ΠΎ всСм ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ - **Composables** - бизнСс-Π»ΠΎΠ³ΠΈΠΊΠ° доступна Π² Ρ€Π°Π·Π½Ρ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°Ρ… - **ΠœΠΈΠΊΡΠΈΠ½Ρ‹ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ** - ΠΌΠΎΠΆΠ½ΠΎ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π°Π·Π½Ρ‹Π΅ composables ### 4. ΠŸΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ - **ЛСнивая Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠ°** - ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΏΠΎΠ΄Π³Ρ€ΡƒΠΆΠ°ΡŽΡ‚ΡΡ ΠΏΠΎ ΠΌΠ΅Ρ€Π΅ нСобходимости - **ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΡ Ρ€Π΅Π½Π΄Π΅Ρ€ΠΈΠ½Π³Π°** - ΠΌΠ΅Π»ΠΊΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ Π»ΡƒΡ‡ΡˆΠ΅ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΡŽΡ‚ΡΡ Vue - **МСньший Π±Π°Π½Π΄Π»** - ΠΊΠΎΠ΄ раздСляСтся Π½Π° Ρ‡Π°Π½ΠΊΠΈ ## πŸ“‹ Руководство ΠΏΠΎ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ### Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ 1. **Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ composable для бизнСс-Π»ΠΎΠ³ΠΈΠΊΠΈ:** ```javascript // composables/game/useNewFeature.js export function useNewFeature() { const state = ref(null) const doSomething = () => { // Π»ΠΎΠ³ΠΈΠΊΠ° } return { state, doSomething } } ``` 2. **Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ UI ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΏΡ€ΠΈ нСобходимости:** ```vue ``` 3. **Π˜Π½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΡƒΠΉΡ‚Π΅ Π² HomePage.vue:** ```vue ``` ### ΠœΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΡ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ 1. **НайдитС ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ composable** 2. **Π˜Π·ΠΌΠ΅Π½ΠΈΡ‚Π΅ Π»ΠΎΠ³ΠΈΠΊΡƒ Π² composable** 3. **ΠžΠ±Π½ΠΎΠ²ΠΈΡ‚Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΏΡ€ΠΈ нСобходимости** 4. **ΠŸΡ€ΠΎΡ‚Π΅ΡΡ‚ΠΈΡ€ΡƒΠΉΡ‚Π΅ измСнСния** ### Π”ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Π½ΠΎΠ²ΠΎΠ³ΠΎ UI ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π° 1. **Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π² ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ ΠΏΠ°ΠΏΠΊΠ΅:** - `components/ui/` - ΠΎΠ±Ρ‰ΠΈΠ΅ UI ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ - `components/game/` - ΠΈΠ³Ρ€ΠΎΠ²Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ - `components/shift/` - ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ смСн 2. **Π‘Π΄Π΅Π»Π°ΠΉΡ‚Π΅ Π΅Π³ΠΎ ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΌ:** ```vue ``` 3. **Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования** ## πŸ§ͺ ВСстированиС ### ВСстированиС composables ```javascript // tests/composables/useGamePorts.spec.js import { useGamePorts } from '@/composables/game/useGamePorts' describe('useGamePorts', () => { it('Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎΡ€Ρ‚Ρ‹', () => { const { gamePorts } = useGamePorts() expect(gamePorts.value).toHaveLength(6) }) it('Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΊΠ»ΠΈΠΊ ΠΏΠΎ ΠΏΠΎΡ€Ρ‚Ρƒ', () => { const { handlePortClick } = useGamePorts() const consoleSpy = vi.spyOn(console, 'log') handlePortClick(1) expect(consoleSpy).toHaveBeenCalledWith('Клик ΠΏΠΎ ΠΏΠΎΡ€Ρ‚Ρƒ:', 1) }) }) ``` ### ВСстированиС ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ```javascript // tests/components/GamePort.spec.js import { mount } from '@vue/test-utils' import GamePort from '@/components/game/GamePort.vue' describe('GamePort', () => { it('Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Ρ‚ΡŒ Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠΎΡ€Ρ‚Π°', () => { const port = { id: 1, active: false, occupied: false } const wrapper = mount(GamePort, { props: { port } }) expect(wrapper.find('.port-number').text()).toBe('1') }) it('Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΠΌΠ΅Ρ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹Π΅ классы для Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ€Ρ‚Π°', () => { const port = { id: 1, active: true, occupied: false } const wrapper = mount(GamePort, { props: { port } }) expect(wrapper.classes()).toContain('active') }) }) ``` ## πŸ” Best Practices ### 1. Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° composables ```javascript // βœ… Π₯ΠΎΡ€ΠΎΡˆΠΎ export function useShiftOperations() { // БостояниС const shiftStatus = ref(null) // ΠœΠ΅Ρ‚ΠΎΠ΄Ρ‹ const openShift = async () => { // Π»ΠΎΠ³ΠΈΠΊΠ° } const closeShift = async () => { // Π»ΠΎΠ³ΠΈΠΊΠ° } // Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΠ΅ return { shiftStatus, openShift, closeShift } } ``` ### 2. ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок ```javascript // βœ… Π₯ΠΎΡ€ΠΎΡˆΠΎ const openShift = async () => { try { const response = await api.openShift() return { success: true, data: response } } catch (error) { console.error('Ошибка открытия смСны:', error) return { success: false, error: error.message } } } ``` ### 3. Валидация props ```javascript // βœ… Π₯ΠΎΡ€ΠΎΡˆΠΎ const props = defineProps({ variant: { type: String, default: 'default', validator: (value) => ['default', 'danger', 'warning'].includes(value) }, size: { type: String, default: 'md', validator: (value) => ['sm', 'md', 'lg'].includes(value) } }) ``` ### 4. ИспользованиС computed свойств ```javascript // βœ… Π₯ΠΎΡ€ΠΎΡˆΠΎ const canManageShift = computed(() => { return user.value?.group === 3 || user.value?.taccess === 'operators' || user.value?.taccess === 'admins' }) ``` ## 🚨 Π˜Π·Π²Π΅ΡΡ‚Π½Ρ‹Π΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹ ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ### ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° 1: Π‘Π»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ WebSocket **РСшСниС:** Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ composable для логирования: ```javascript // composables/debug/useWebSocketLogger.js export function useWebSocketLogger() { const logMessage = (message, direction = 'send') => { console.log(`[${direction.toUpperCase()}]`, new Date().toISOString(), message) } return { logMessage } } ``` ### ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° 2: Бинхронизация состояния ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ **РСшСниС:** Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ reactive ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Π² composables: ```javascript // composables/shared/useGameState.js const gameState = reactive({ isPaused: false, activePorts: [], currentShift: null }) export function useGameState() { return { gameState } } ``` ### ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° 3: ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° мноТСствСнных асинхронных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ **РСшСниС:** Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Promise.all ΠΈΠ»ΠΈ async/await с ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ ошибок: ```javascript const initializeApp = async () => { try { const [authResult, shiftStatus, portsStatus] = await Promise.all([ checkAuth(), getShiftsStatus(), getPortsStatus() ]) return { success: true, data: { authResult, shiftStatus, portsStatus } } } catch (error) { return { success: false, error: error.message } } } ``` ## πŸ“ˆ План Π΄Π°Π»ΡŒΠ½Π΅ΠΉΡˆΠΈΡ… ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΠΉ ### ΠšΡ€Π°Ρ‚ΠΊΠΎΡΡ€ΠΎΡ‡Π½Ρ‹Π΅ Ρ†Π΅Π»ΠΈ (1-2 Π½Π΅Π΄Π΅Π»ΠΈ) 1. **Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ TypeScript** для типобСзопасности 2. **ΠΠ°ΠΏΠΈΡΠ°Ρ‚ΡŒ unit тСсты** для основных composables 3. **ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ** с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ lazy loading 4. **Π£Π»ΡƒΡ‡ΡˆΠΈΡ‚ΡŒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ошибок** ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ ΠΎΠΏΡ‹Ρ‚ ### БрСднСсрочныС Ρ†Π΅Π»ΠΈ (1-2 мСсяца) 1. **Π‘ΠΎΠ·Π΄Π°Ρ‚ΡŒ Storybook** для Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² 2. **Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ E2E тСсты** для ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Ρ… сцСнариСв 3. **Π Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΡΡˆΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅** для ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ запросов 4. **Π£Π»ΡƒΡ‡ΡˆΠΈΡ‚ΡŒ ΠΌΠΎΠ±ΠΈΠ»ΡŒΠ½ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ** ### ДолгосрочныС Ρ†Π΅Π»ΠΈ (3-6 мСсяцСв) 1. **ΠœΠΈΠ³Ρ€Π°Ρ†ΠΈΡ Π½Π° Pinia** для управлСния состояниСм 2. **Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ PWA** Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ 3. **ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π±Π°Π½Π΄Π»** ΠΈ врСмя Π·Π°Π³Ρ€ΡƒΠ·ΠΊΠΈ 4. **Π Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Π΅ΠΌΡ‹ оформлСния** ## πŸ“š ΠŸΠΎΠ»Π΅Π·Π½Ρ‹Π΅ рСсурсы ### ДокумСнтация - [Vue 3 Composition API](https://vuejs.org/guide/extras/composition-api-faq.html) - [Vue Router](https://router.vuejs.org/) - [Vite](https://vitejs.dev/) ### Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ - [Vue DevTools](https://devtools.vuejs.org/) - [Vitest](https://vitest.dev/) для тСстирования - [ESLint](https://eslint.org/) для качСства ΠΊΠΎΠ΄Π° - [Prettier](https://prettier.io/) для форматирования ### ΠŸΠ°Ρ‚Ρ‚Π΅Ρ€Π½Ρ‹ ΠΈ Π»ΡƒΡ‡ΡˆΠΈΠ΅ ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠΈ - [Vue Style Guide](https://v2.vuejs.org/v2/style-guide/) - [Composition API Patterns](https://vueuse.org/) - [Vue 3 Best Practices](https://learnvue.co/articles/vue-3-best-practices) --- ## πŸŽ‰ Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Π Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ½Π³ HomePage.vue Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΡƒΠ»ΡƒΡ‡ΡˆΠΈΠ» Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ прилоТСния: - **УмСньшСн Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΊΠΎΠ΄Π°** Π½Π° 75% - **ΠŸΠΎΠ²Ρ‹ΡˆΠ΅Π½Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅ΠΌΠΎΡΡ‚ΡŒ** Ρ‡Π΅Ρ€Π΅Π· ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½ΡƒΡŽ структуру - **Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π° Ρ‚Π΅ΡΡ‚ΠΈΡ€ΡƒΠ΅ΠΌΠΎΡΡ‚ΡŒ** Ρ‡Π΅Ρ€Π΅Π· ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ composables - **Π£Π²Π΅Π»ΠΈΡ‡Π΅Π½ΠΎ ΠΏΠ΅Ρ€Π΅ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½ΠΈΠ΅** ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈ Π»ΠΎΠ³ΠΈΠΊΠΈ ΠŸΡ€ΠΎΠ΅ΠΊΡ‚ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ слСдуСт соврСмСнным ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ°ΠΌ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π½Π° Vue 3 ΠΈ Π³ΠΎΡ‚ΠΎΠ² ΠΊ Π΄Π°Π»ΡŒΠ½Π΅ΠΉΡˆΠ΅ΠΌΡƒ ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ ΠΈ Ρ€Π°Π·Π²ΠΈΡ‚ΠΈΡŽ. --- *ДокумСнтация ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½Π°: {{ new Date().toLocaleDateString('ru-RU') }}* Β§