feat: Phase 3 — Workshop (community patch sharing)

Server:
- GET /api/v1/workshop — browse patches (search, tags, sort)
- POST /api/v1/workshop — share a patch (auth required)
- GET /api/v1/workshop/:id — single patch detail
- DELETE /api/v1/workshop/:id — soft delete (owner/admin)
- POST/DELETE /api/v1/workshop/:id/like — like/unlike
- POST /api/v1/workshop/:id/report — flag for moderation

Client:
- Workshop page with nav bar (Sandbox/SynthQuest/Workshop tabs)
- Search bar + tag filters (ambient, bass, drums, etc.)
- Sort by recent/popular
- Patch cards: title, author, tags, likes, module count
- "Cargar" button loads patch into Sandbox
- Share modal: title, description, tags, shares current canvas
- User badge + login button in Workshop nav
- Responsive: single column on mobile

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jose Luis
2026-03-21 20:33:53 +01:00
parent 64ffa36c09
commit 982654c3ef
7 changed files with 548 additions and 6 deletions

View File

@@ -2,19 +2,25 @@ import React, { useState } from 'react';
import { createRoot } from 'react-dom/client';
import App from './App';
import GameApp from './game/GameApp.jsx';
import Workshop from './components/Workshop.jsx';
import { AuthProvider } from './services/AuthContext.jsx';
import AuthModal from './components/AuthModal.jsx';
import './index.css';
function Root() {
const [mode, setMode] = useState('game'); // 'game' | 'sandbox'
const [mode, setMode] = useState('game'); // 'game' | 'sandbox' | 'workshop'
const nav = {
toGame: () => setMode('game'),
toSandbox: () => setMode('sandbox'),
toWorkshop: () => setMode('workshop'),
};
return (
<AuthProvider>
{mode === 'sandbox'
? <App onSwitchToGame={() => setMode('game')} />
: <GameApp onSwitchToSandbox={() => setMode('sandbox')} />
}
{mode === 'sandbox' && <App onSwitchToGame={nav.toGame} onSwitchToWorkshop={nav.toWorkshop} />}
{mode === 'game' && <GameApp onSwitchToSandbox={nav.toSandbox} onSwitchToWorkshop={nav.toWorkshop} />}
{mode === 'workshop' && <Workshop onSwitchToSandbox={nav.toSandbox} onSwitchToGame={nav.toGame} />}
<AuthModal />
</AuthProvider>
);