6.1 KiB
6.1 KiB
Документация по переносу компонента GamePort (Порт игры)
Общая структура в React
- Файл: client/src/components/GamePort.tsx
- Тип: React.memo функциональный компонент с props (portNumber, onStartGame, movingGame/Player, onStartMovingGame/Player, onMoveGameTo/PlayerTo).
- Зависимости: react-redux (useSelector/dispatch), hooks (useWebSocketNew, useAuth, useIsMobile, useDeviceType, useNotifications), icons (Io*, Fa*), components (Button, Card, Badge, BonusProgress, modals).
- State: timer, showConfirmation (type: endGame/cancelGame/forceEndGame), showDeleteModal, isDragging, dragType, forceDragEffect, showTechConfirm.
- Template (JSX): Card relative w-full h-full (bg по статусу, border, cursor-pointer), absolute элементы (gun icon, timer, buttons), main div flex-col justify-center, modals (ConfirmationModal, PlayerDeleteModal, tech confirm).
- Computed: isActive, hasPlayer, canHaveBonus, isPaused, highlight, isMovingDestination/Source, canDropHere, canManageGame/Player, canDragGame/Player, canCloseGame, isLockedForTechnic/Operator.
- Effects: useEffect for timer (interval 1000), drag events (start/end/over/enter/leave/drop), debug logs.
Элементы
- Статус порта: Card class "game-port-card" (bg-slate-700 idle, bg-gray-700 player, bg-blue/green/orange/cyan active), relative, draggable, onClick handlePortClick, onDrag* handlers.
- Gun icon: absolute top-1 left-1, FaGun green (connected) or gray line-through + FaBan red (disconnected).
- Timer: absolute top-1 left-8, div bg-black text-white rounded p-2 text-xs monospace.
- Lock overlay: absolute inset-0 bg-slate-900/70 flex center FaLock (for restricted access).
- Drag overlay: absolute inset-0 bg-green-500/30 flex center arrow-down text (if canDropHere).
- Контент:
- Number: div text-4xl font-bold {portNumber}.
- Game name: div text-xs font-semibold {getGameName(port.game)} (e.g., "Пристрелка", "Игра 3").
- Bonus: div text-xs "Бонусная".
- Player: div text-xs "Игрок #{gamerId}".
- Stats: div flex space-x-2, badges "🎯 {patrOk}", "➕ {patrAdd}".
- Patron controls: flex space-x-2, MinusButton/PlusButton (disabled if paused/0), div {patr} text-2xl.
- Buttons (absolute top-1 right-1 flex gap-2, z-10):
- Move game: Button bg-gray-600 hover:bg-gray-700, IoSwapHorizontalOutline, title "Перенести игру", disabled paused, onClick handleStartMovingGame.
- Cancel: Button bg-orange-600 hover:bg-orange-700, IoClose, title "Отменить игру", disabled paused, onClick handleCancelGame.
- Delete player: Button bg-red-600 hover:bg-red-700, IoTrashOutline, title "Удалить", disabled paused, onClick handleRemovePlayer.
- For empty port: "Свободен", "Нажмите для создания" green if smena open.
- For player port: "Игрок", "Игр: {gameCounter}", pause badge if paused.
- For active: game name, bonus, player, patron controls, stats.
- Modals:
- Tech confirm: fixed inset-0 bg-black/60 flex center, content bg-slate-800 p-8, h2 "Техническая пристрелка", buttons "Запустить пристрелку" green, "Отмена" gray.
- ConfirmationModal: isOpen=showConfirmation.show, type (endGame/cancel/forceEnd), portNumber, onConfirm.
- PlayerDeleteModal: isOpen=showDeleteModal, gamerId, portNumber, gameCounter, onConfirm.
- Drag&Drop: draggable=true, data-port={portNumber}, classes (port-dragging, drag-over, can-drop), effects (scale, opacity).
Стили (Tailwind примеры)
- Card: relative border-2 cursor-pointer w-full h-full min-h-[160px] mobile, [220px] desktop, flex flex-col justify-between, bg-slate-700 border-slate-600 (idle), bg-gray-700 (player), bg-blue-600 (game), bg-orange-600 (tech shot), bg-cyan-500 (shot), transition-all hover:border-white hover:shadow-xl.
- Absolute buttons: top-1 right-1 flex gap-2 z-10, Button size="sm" variant="ghost" bg-gray-600 hover:bg-gray-700 rounded text-white.
- Patron: flex justify-center space-x-2, Button size="sm" variant="ghost" rounded text-white hover:bg-opacity-60, div text-2xl font-bold min-w-[45px].
- Responsive: @media min-width 769px — min-h-[300px], desktop-port-card; mobile — min-h-[120px], game-port-card; tablet — game-port-card-tablet min-h-[180px].
- Drag: .port-dragging opacity-50 scale-98, .drag-over ring-4 ring-green-400 bg-green-500/20 scale-101, .can-drop border-yellow-400 bg-yellow-600.
- Animations: animate-pulse for highlight (ring-4 ring-*-400), grayscale opacity-50 for paused/locked.
Взаимодействие
- onClick port: handlePortClick — check role/pause/smena/ESP, open modal or start game, drag if moving.
- Buttons: handleStartMovingGame/Player (dispatch movingStarted), handlePatronChange (+/-1 via WebSocket 'addp'), handleStopGame/Cancel/ForceEnd (set showConfirmation), handleRemovePlayer (set showDeleteModal).
- Drag: handleDragStart (set data, class dragging), handleDrop (send 'move'/'moveGamer' via WebSocket, animation with createFlyingPortAnimation), handleDragOver/Enter/Leave (preventDefault, set isDragOver).
- Modals: Confirmation for end/cancel/forceEnd (onConfirm send 'endGame'/'cancelGame'/'forceEndGame'), PlayerDelete (send 'deleteGamer'), TechConfirm for tech shot (send 'start' game=2).
- Effects: timer interval if active, drag end cancel moving, logs for debug.
- In Dashboard: <GamePort v-for portNumber=1 to 6, :props, @start-game, @start-moving />.
Vue маппинг
- : <Card :class="portClass" @click="handlePortClick" draggable="!paused && canDrag" @dragstart="handleDragStart" @drop="handleDrop" :data-port="portNumber"> absolute gun/timer/buttons, main div flex-col, v-if status elements, v-for badges.
- Props: portNumber, onStartGame, movingGame/Player, onStartMovingGame/Player.
- Emits: start-moving-game/player, move-game/player-to.
- Composables: useGameStore (computed status), useWebSocket (sendMessage), useNotifications (show*), useAuth (role).
- v-model for modals, @drag* handlers, style for bg/shadow based on computed.
- Teleport for modals, v-if for lock overlay/drag overlay.