Redesign UI with Vuetify and improve configuration

Major changes:
- Full UI redesign with Vuetify 3 (dark theme, modern components)
- Sidebar navigation with gradient logo
- Redesigned player controls with Material Design icons
- New room cards, track lists, and filter UI with chips
- Modern auth pages with centered cards

Configuration improvements:
- Centralized all settings in root .env file
- Removed redundant backend/.env and frontend/.env files
- Increased file upload limit to 100MB (nginx + backend)
- Added build args for Vite environment variables
- Frontend now uses relative paths (better for domain deployment)

UI Components updated:
- App.vue: v-navigation-drawer with sidebar
- MiniPlayer: v-footer with modern controls
- Queue: v-list with styled items
- RoomView: improved filters with clickable chips
- All views: Vuetify cards, buttons, text fields

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-19 20:17:52 +03:00
parent 8a2ea5b4af
commit ee8d79d155
26 changed files with 1498 additions and 833 deletions

View File

@@ -24,7 +24,7 @@ class Settings(BaseSettings):
max_room_participants: int = 50
class Config:
env_file = ".env"
# env_file не нужен - переменные передаются через docker-compose
extra = "ignore"

View File

@@ -7,7 +7,7 @@ from ..database import get_db
from ..models.user import User
from ..models.room import Room, RoomParticipant
from ..models.track import RoomQueue
from ..schemas.room import RoomCreate, RoomResponse, RoomDetailResponse, QueueAdd, QueueAddMultiple
from ..schemas.room import RoomCreate, RoomResponse, RoomDetailResponse, QueueAdd, QueueAddMultiple, QueueItemResponse
from ..schemas.track import TrackResponse
from ..schemas.user import UserResponse
from ..services.auth import get_current_user
@@ -178,7 +178,7 @@ async def leave_room(
return {"status": "left"}
@router.get("/{room_id}/queue", response_model=list[TrackResponse])
@router.get("/{room_id}/queue", response_model=list[QueueItemResponse])
async def get_queue(room_id: UUID, db: AsyncSession = Depends(get_db)):
result = await db.execute(
select(RoomQueue)
@@ -187,7 +187,13 @@ async def get_queue(room_id: UUID, db: AsyncSession = Depends(get_db)):
.order_by(RoomQueue.position)
)
queue_items = result.scalars().all()
return [TrackResponse.model_validate(item.track) for item in queue_items]
return [
QueueItemResponse(
track=TrackResponse.model_validate(item.track),
added_by=item.added_by
)
for item in queue_items
]
@router.post("/{room_id}/queue")
@@ -314,13 +320,25 @@ async def remove_from_queue(
)
queue_item = result.scalar_one_or_none()
if queue_item:
await db.delete(queue_item)
# Notify others
await manager.broadcast_to_room(
room_id,
{"type": "queue_updated"},
if not queue_item:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Track not in queue"
)
# Check if user added this track to queue
if queue_item.added_by != current_user.id:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Can only remove tracks you added"
)
await db.delete(queue_item)
# Notify others
await manager.broadcast_to_room(
room_id,
{"type": "queue_updated"},
)
return {"status": "removed"}

View File

@@ -49,3 +49,16 @@ class QueueAdd(BaseModel):
class QueueAddMultiple(BaseModel):
track_ids: list[UUID]
class QueueItemResponse(BaseModel):
track: "TrackResponse"
added_by: UUID
class Config:
from_attributes = True
# Import at the end to avoid circular imports
from .track import TrackResponse
QueueItemResponse.model_rebuild()