From efbb15c3c372990152a77abd9fb05556aee371b3 Mon Sep 17 00:00:00 2001 From: Junior331 Date: Sat, 14 Jun 2025 17:11:52 -0300 Subject: [PATCH 01/27] Enhance scene management by integrating a ScenesProvider for improved context handling, updating the Header component to allow scene creation, and refining the Modal component for better scene editing functionality. Additionally, streamline the Studio component to utilize the new scenes context and remove redundant state management. --- package.json | 1 + src/App.tsx | 15 +++-- src/components/button/index.tsx | 6 +- src/components/header/index.tsx | 29 ++++++-- src/components/modal/index.tsx | 105 +++++++++++++++-------------- src/contexts/production.tsx | 113 ++++++++++++++++---------------- src/contexts/scenes.tsx | 91 +++++++++++++++++++++++++ src/pages/Studio/index.tsx | 54 ++++----------- src/reducers/scenes.ts | 1 + 9 files changed, 254 insertions(+), 161 deletions(-) create mode 100644 src/contexts/scenes.tsx diff --git a/package.json b/package.json index 9b54b86..ab4dce1 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-refresh": "^0.4.20", "globals": "^16.2.0", + "json-server": "1.0.0-beta.3", "typescript": "~5.8.3", "typescript-eslint": "^8.33.0", "vite": "^6.3.5" diff --git a/src/App.tsx b/src/App.tsx index c0ff118..7172574 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,13 +1,16 @@ -import {ProductionProvider} from "./contexts/production" -import Routes from "./routes" -import "./styles/global.css" +import { ProductionProvider } from './contexts/production'; +import { ScenesProvider } from './contexts/scenes'; +import Routes from './routes'; +import './styles/global.css'; function App() { return ( - + + + - ) + ); } -export default App +export default App; diff --git a/src/components/button/index.tsx b/src/components/button/index.tsx index 4fcc7d0..e4005b4 100644 --- a/src/components/button/index.tsx +++ b/src/components/button/index.tsx @@ -6,7 +6,7 @@ import {type VariantProps, cva} from 'class-variance-authority'; import {cn} from '../../utils/cn'; const buttonVariants = cva( - 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50', + 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 cursor-pointer', { variants: { variant: { @@ -31,7 +31,7 @@ const buttonVariants = cva( } ); -interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { +interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { asChild?: boolean; } @@ -39,7 +39,7 @@ const Button = forwardRef( ({ className, variant, size, asChild = false, ...props }, ref) => { const Comp = asChild ? HeadlessButton : 'button'; return ( - ; + ); }, ); diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx index 58a2892..efaaa85 100644 --- a/src/components/header/index.tsx +++ b/src/components/header/index.tsx @@ -1,7 +1,26 @@ -import {Button} from "../button" -import {Input} from "../input" +import { useScenes } from '../../contexts/scenes'; +import { Button } from '../button'; +import { Input } from '../input'; +import { type SceneDetails } from '../modal'; export function Header() { + const { scenes, createScene } = useScenes(); + + const handleCreateScene = async () => { + const newScene: SceneDetails = { + id: (scenes.length + 1).toString(), + title: 'Nova Cena', + description: '', + step: 1, + columnId: 'column-1', + episode: '1', + recordDate: new Date().toISOString().split('T')[0], + recordLocation: '', + }; + + await createScene(newScene); + }; + return (
@@ -10,7 +29,9 @@ export function Header() {
- +
@@ -20,5 +41,5 @@ export function Header() {
- ) + ); } diff --git a/src/components/modal/index.tsx b/src/components/modal/index.tsx index 94114dd..775a3c4 100644 --- a/src/components/modal/index.tsx +++ b/src/components/modal/index.tsx @@ -1,64 +1,69 @@ -import {Fragment, useState} from "react" +import { Fragment, useState } from 'react'; -import {Dialog, DialogPanel, DialogTitle, Transition, TransitionChild} from "@headlessui/react" -import {XIcon} from "lucide-react" +import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react'; +import { XIcon } from 'lucide-react'; -import {type Scene as SceneDetails} from "../../reducers/scenes" +import { type Scene as SceneDetails } from '../../reducers/scenes'; interface ModalProps { - isOpen: boolean - onClose: () => void - scene?: SceneDetails - onUpdate?: (scene: SceneDetails) => void + isOpen: boolean; + onClose: () => void; + scene?: SceneDetails; + onUpdate?: (scene: SceneDetails) => void; } -const steps: Record = { - 1: "Roteirizado", - 2: "Em pré-produção", - 3: "Em gravação", - 4: "Em pós-produção", - 5: "Finalizado" -} - -const Modal = ({isOpen, onClose, scene, onUpdate}: ModalProps) => { - const [editedScene, setEditedScene] = useState(scene) - const [isSaving, setIsSaving] = useState(false) +const Modal = ({ isOpen, onClose, scene, onUpdate }: ModalProps) => { + const [editedScene, setEditedScene] = useState(scene); + const [isSaving, setIsSaving] = useState(false); const handleChange = (field: keyof SceneDetails, value: string | number) => { - if (!editedScene) return + if (!editedScene) return; - if (field === "recordDate") { - const date = new Date(value as string) - if (date.toString() === "Invalid Date") { - setEditedScene({...editedScene, [field as string]: value}) - return + if (field === 'recordDate') { + const date = new Date(value as string); + if (date.toString() === 'Invalid Date') { + setEditedScene({ ...editedScene, [field as string]: value }); + return; } } - setEditedScene({...editedScene, [field]: value}) - } + setEditedScene({ ...editedScene, [field]: value }); + }; const handleSave = async () => { - if (!editedScene || !onUpdate) return + if (!editedScene || !onUpdate) return; - setIsSaving(true) + setIsSaving(true); await fetch(`${import.meta.env.VITE_API_URL}/scenes/${editedScene.id}`, { - method: "POST", + method: 'POST', headers: { - "Content-Type": "application/json" + 'Content-Type': 'application/json', }, body: JSON.stringify({ ...editedScene, updatedAt: new Date().toISOString(), - version: Math.random() - }) - }) - - onUpdate(editedScene) - onClose() - setIsSaving(false) - } + version: Math.random(), + }), + }); + + onUpdate(editedScene); + onClose(); + setIsSaving(false); + }; + + const STEPS: Record = { + 1: 'Roteirizado', + 2: 'Em pré-produção', + 3: 'Em gravação', + 4: 'Em pós-produção', + 5: 'Finalizado', + }; + + const nextStep = scene?.step ? scene.step + 1 : 1; + const availableSteps = Object.entries(STEPS).filter( + ([step]) => Number(step) === scene?.step || Number(step) === nextStep, + ); return ( @@ -106,7 +111,7 @@ const Modal = ({isOpen, onClose, scene, onUpdate}: ModalProps) => { handleChange("title", e.target.value)} + onChange={(e) => handleChange('title', e.target.value)} className='mt-1 w-full rounded-md border border-border bg-background px-3 py-2 text-primary focus:outline-none focus:ring-2 focus:ring-primary/50' /> @@ -115,7 +120,7 @@ const Modal = ({isOpen, onClose, scene, onUpdate}: ModalProps) => {

Descrição