diff --git a/data/api.json b/data/api.json index 45eb641..fc917fc 100644 --- a/data/api.json +++ b/data/api.json @@ -38,31 +38,45 @@ "description": "Cenas finalizadas" } ], + "actors": [ + { + "id": "1", + "name": "Jaja", + "bio": "Ator principal com experiência em teatro e TV", + "scenes": [] + } + ], "scenes": [ { "id": "1", - "title": "A Chegada", + "title": "A Chegada 2", "description": "João chega à cidade em busca de uma nova vida", - "step": 1, + "step": 2, "episode": "1", "columnId": "column-1", - "recordDate": "2000-03-15", + "recordDate": "2026-03-15", "recordLocation": "Estúdio Central", - "updatedAt": "2025-06-05T23:23:13.281Z", - "version": 0.9819784473304957 + "order": 20, + "updatedAt": "2025-06-16T16:26:31.504Z", + "version": 0.02944438360700985 }, { "id": "2", - "step": 2, + "title": "O Encontro 2", + "description": "João conhece Maria na praça da cidade", + "step": 3, "episode": "1", - "title": "O Encontro", "columnId": "column-2", - "recordDate": "2024-03-20", + "recordDate": "2026-03-20", "recordLocation": "Praça Central", - "description": "João conhece Maria na praça da cidade" + "order": 20, + "actors": [], + "updatedAt": "2025-06-17T02:05:47.821Z", + "version": 0.26566516779415716 }, { "id": "3", + "order": 2, "step": 3, "episode": "1", "title": "A Conversa", @@ -73,6 +87,7 @@ }, { "id": "4", + "order": 3, "step": 4, "episode": "1", "title": "O Desafio", @@ -83,6 +98,7 @@ }, { "id": "5", + "order": 4, "step": 5, "episode": "1", "title": "A Vitória", @@ -93,26 +109,34 @@ }, { "id": "6", - "step": 1, + "order": 21, + "step": 2, "episode": "2", "title": "Novos Horizontes", "columnId": "column-6", "recordDate": "2024-04-10", "recordLocation": "Estúdio Central", - "description": "Maria apresenta João a novos amigos" + "description": "Maria apresenta João a novos amigos", + "updatedAt": "2025-06-16T16:26:37.455Z", + "version": 0.971949121331033 }, { "id": "7", - "step": 2, + "title": "O Projeto 2", + "description": "João e Maria começam um projeto juntos", + "step": 3, "episode": "2", - "title": "O Projeto", - "columnId": "column-7", - "recordDate": "2024-04-15", + "recordDate": "2029-04-15", "recordLocation": "Sala de Reuniões", - "description": "João e Maria começam um projeto juntos" + "columnId": "column-7", + "order": 21, + "actors": [], + "updatedAt": "2025-06-17T03:16:30.519Z", + "version": 0.7616206455723247 }, { "id": "8", + "order": 7, "step": 3, "episode": "2", "title": "Os Obstáculos", @@ -123,6 +147,7 @@ }, { "id": "9", + "order": 8, "step": 4, "episode": "2", "title": "A Superação", @@ -133,6 +158,7 @@ }, { "id": "10", + "order": 9, "step": 5, "episode": "2", "title": "O Sucesso", @@ -143,17 +169,21 @@ }, { "id": "11", - "step": 1, + "order": 22, + "step": 2, "episode": "3", "title": "A Mudança", "columnId": "column-11", "recordDate": "2024-05-05", "recordLocation": "Estúdio Central", - "description": "João decide mudar de cidade" + "description": "João decide mudar de cidade", + "updatedAt": "2025-06-16T16:26:47.742Z", + "version": 0.1521792912180978 }, { "id": "12", - "step": 2, + "order": 22, + "step": 3, "episode": "3", "title": "A Despedida", "columnId": "column-12", @@ -163,6 +193,7 @@ }, { "id": "13", + "order": 12, "step": 3, "episode": "3", "title": "A Saudade", @@ -173,6 +204,7 @@ }, { "id": "14", + "order": 13, "step": 4, "episode": "3", "title": "A Decisão", @@ -183,6 +215,7 @@ }, { "id": "15", + "order": 14, "step": 5, "episode": "3", "title": "O Reencontro", @@ -193,16 +226,21 @@ }, { "id": "16", + "title": "Novos Planos", + "description": "O casal faz novos planos juntos", "step": 1, "episode": "4", - "title": "Novos Planos", - "columnId": "column-16", "recordDate": "2024-06-01", "recordLocation": "Café", - "description": "O casal faz novos planos juntos" + "columnId": "column-16", + "order": 15, + "actors": [ + "1" + ] }, { "id": "17", + "order": 16, "step": 2, "episode": "4", "title": "A Busca", @@ -213,6 +251,7 @@ }, { "id": "18", + "order": 17, "step": 3, "episode": "4", "title": "A Escolha", @@ -223,6 +262,7 @@ }, { "id": "19", + "order": 18, "step": 4, "episode": "4", "title": "A Mudança", @@ -233,6 +273,7 @@ }, { "id": "20", + "order": 19, "step": 5, "episode": "4", "title": "A Festa", @@ -243,6 +284,7 @@ }, { "id": "21", + "order": 20, "step": 1, "episode": "5", "title": "O Trabalho", @@ -253,6 +295,7 @@ }, { "id": "22", + "order": 21, "step": 2, "episode": "5", "title": "A Adaptação", @@ -263,6 +306,7 @@ }, { "id": "23", + "order": 22, "step": 3, "episode": "5", "title": "Os Colegas", @@ -273,6 +317,7 @@ }, { "id": "24", + "order": 23, "step": 4, "episode": "5", "title": "O Projeto", @@ -283,6 +328,7 @@ }, { "id": "25", + "order": 24, "step": 5, "episode": "5", "title": "O Sucesso", @@ -293,6 +339,7 @@ }, { "id": "26", + "order": 25, "step": 1, "episode": "6", "title": "A Promoção", @@ -303,6 +350,7 @@ }, { "id": "27", + "order": 26, "step": 2, "episode": "6", "title": "A Celebração", @@ -313,6 +361,7 @@ }, { "id": "28", + "order": 27, "step": 3, "episode": "6", "title": "Os Novos Desafios", @@ -323,6 +372,7 @@ }, { "id": "29", + "order": 28, "step": 4, "episode": "6", "title": "A Equipe", @@ -333,6 +383,7 @@ }, { "id": "30", + "order": 29, "step": 5, "episode": "6", "title": "O Resultado", @@ -343,6 +394,7 @@ }, { "id": "31", + "order": 30, "step": 1, "episode": "7", "title": "A Viagem", @@ -353,6 +405,7 @@ }, { "id": "32", + "order": 31, "step": 2, "episode": "7", "title": "O Encontro", @@ -363,6 +416,7 @@ }, { "id": "33", + "order": 32, "step": 3, "episode": "7", "title": "A Negociação", @@ -373,6 +427,7 @@ }, { "id": "34", + "order": 33, "step": 4, "episode": "7", "title": "O Contrato", @@ -383,6 +438,7 @@ }, { "id": "35", + "order": 34, "step": 5, "episode": "7", "title": "O Retorno", @@ -393,6 +449,7 @@ }, { "id": "36", + "order": 35, "step": 1, "episode": "8", "title": "A Surpresa", @@ -403,6 +460,7 @@ }, { "id": "37", + "order": 36, "step": 2, "episode": "8", "title": "A Decisão", @@ -413,6 +471,7 @@ }, { "id": "38", + "order": 37, "step": 3, "episode": "8", "title": "O Momento", @@ -423,6 +482,7 @@ }, { "id": "39", + "order": 38, "step": 4, "episode": "8", "title": "A Celebração", @@ -433,6 +493,7 @@ }, { "id": "40", + "order": 39, "step": 5, "episode": "8", "title": "O Futuro", @@ -443,6 +504,7 @@ }, { "id": "41", + "order": 40, "step": 1, "episode": "9", "title": "A Mudança", @@ -453,6 +515,7 @@ }, { "id": "42", + "order": 41, "step": 2, "episode": "9", "title": "A Adaptação", @@ -463,6 +526,7 @@ }, { "id": "43", + "order": 42, "step": 3, "episode": "9", "title": "Os Desafios", @@ -473,6 +537,7 @@ }, { "id": "44", + "order": 43, "step": 4, "episode": "9", "title": "A Superação", @@ -483,6 +548,7 @@ }, { "id": "45", + "order": 44, "step": 5, "episode": "9", "title": "O Sucesso", @@ -493,6 +559,7 @@ }, { "id": "46", + "order": 45, "step": 1, "episode": "10", "title": "O Projeto", @@ -503,6 +570,7 @@ }, { "id": "47", + "order": 46, "step": 2, "episode": "10", "title": "A Equipe", @@ -513,6 +581,7 @@ }, { "id": "48", + "order": 47, "step": 3, "episode": "10", "title": "O Desenvolvimento", @@ -523,6 +592,7 @@ }, { "id": "49", + "order": 48, "step": 4, "episode": "10", "title": "Os Ajustes", @@ -533,6 +603,7 @@ }, { "id": "50", + "order": 49, "step": 5, "episode": "10", "title": "A Conclusão", @@ -543,6 +614,7 @@ }, { "id": "51", + "order": 50, "step": 1, "episode": "11", "title": "A Viagem", @@ -553,6 +625,7 @@ }, { "id": "52", + "order": 51, "step": 2, "episode": "11", "title": "O Destino", @@ -563,6 +636,7 @@ }, { "id": "53", + "order": 52, "step": 3, "episode": "11", "title": "A Exploração", @@ -573,6 +647,7 @@ }, { "id": "54", + "order": 53, "step": 4, "episode": "11", "title": "As Descobertas", @@ -583,6 +658,7 @@ }, { "id": "55", + "order": 54, "step": 5, "episode": "11", "title": "O Retorno", @@ -593,6 +669,7 @@ }, { "id": "56", + "order": 55, "step": 1, "episode": "12", "title": "A Festa", @@ -603,6 +680,7 @@ }, { "id": "57", + "order": 56, "step": 2, "episode": "12", "title": "Os Convidados", @@ -613,6 +691,7 @@ }, { "id": "58", + "order": 57, "step": 3, "episode": "12", "title": "A Celebração", @@ -623,6 +702,7 @@ }, { "id": "59", + "order": 58, "step": 4, "episode": "12", "title": "Os Momentos", @@ -633,6 +713,7 @@ }, { "id": "60", + "order": 59, "step": 5, "episode": "12", "title": "A Despedida", @@ -643,6 +724,7 @@ }, { "id": "61", + "order": 60, "step": 1, "episode": "13", "title": "O Ano Novo", @@ -653,6 +735,7 @@ }, { "id": "62", + "order": 61, "step": 2, "episode": "13", "title": "As Metas", @@ -663,6 +746,7 @@ }, { "id": "63", + "order": 62, "step": 3, "episode": "13", "title": "Os Objetivos", @@ -673,6 +757,7 @@ }, { "id": "64", + "order": 63, "step": 4, "episode": "13", "title": "O Plano", @@ -683,6 +768,7 @@ }, { "id": "65", + "order": 64, "step": 5, "episode": "13", "title": "A Execução", @@ -693,6 +779,7 @@ }, { "id": "66", + "order": 65, "step": 1, "episode": "14", "title": "O Desafio", @@ -703,6 +790,7 @@ }, { "id": "67", + "order": 66, "step": 2, "episode": "14", "title": "A Preparação", @@ -713,6 +801,7 @@ }, { "id": "68", + "order": 67, "step": 3, "episode": "14", "title": "O Enfrentamento", @@ -723,6 +812,7 @@ }, { "id": "69", + "order": 68, "step": 4, "episode": "14", "title": "A Superação", @@ -733,6 +823,7 @@ }, { "id": "70", + "order": 69, "step": 5, "episode": "14", "title": "A Vitória", @@ -743,6 +834,7 @@ }, { "id": "71", + "order": 70, "step": 1, "episode": "15", "title": "A Mudança", @@ -753,6 +845,7 @@ }, { "id": "72", + "order": 71, "step": 2, "episode": "15", "title": "A Adaptação", @@ -763,6 +856,7 @@ }, { "id": "73", + "order": 72, "step": 3, "episode": "15", "title": "Os Novos Caminhos", @@ -773,6 +867,7 @@ }, { "id": "74", + "order": 73, "step": 4, "episode": "15", "title": "As Descobertas", @@ -783,6 +878,7 @@ }, { "id": "75", + "order": 74, "step": 5, "episode": "15", "title": "O Futuro", @@ -793,6 +889,7 @@ }, { "id": "76", + "order": 75, "step": 1, "episode": "16", "title": "O Projeto", @@ -803,6 +900,7 @@ }, { "id": "77", + "order": 76, "step": 2, "episode": "16", "title": "A Equipe", @@ -813,6 +911,7 @@ }, { "id": "78", + "order": 77, "step": 3, "episode": "16", "title": "O Desenvolvimento", @@ -823,6 +922,7 @@ }, { "id": "79", + "order": 78, "step": 4, "episode": "16", "title": "Os Ajustes", @@ -833,6 +933,7 @@ }, { "id": "80", + "order": 79, "step": 5, "episode": "16", "title": "A Conclusão", @@ -843,6 +944,7 @@ }, { "id": "81", + "order": 80, "step": 1, "episode": "17", "title": "A Viagem", @@ -853,6 +955,7 @@ }, { "id": "82", + "order": 81, "step": 2, "episode": "17", "title": "O Destino", @@ -863,6 +966,7 @@ }, { "id": "83", + "order": 82, "step": 3, "episode": "17", "title": "A Exploração", @@ -873,6 +977,7 @@ }, { "id": "84", + "order": 83, "step": 4, "episode": "17", "title": "As Descobertas", @@ -883,6 +988,7 @@ }, { "id": "85", + "order": 84, "step": 5, "episode": "17", "title": "O Retorno", @@ -893,6 +999,7 @@ }, { "id": "86", + "order": 85, "step": 1, "episode": "18", "title": "A Festa", @@ -903,6 +1010,7 @@ }, { "id": "87", + "order": 86, "step": 2, "episode": "18", "title": "Os Convidados", @@ -913,6 +1021,7 @@ }, { "id": "88", + "order": 87, "step": 3, "episode": "18", "title": "A Celebração", @@ -923,6 +1032,7 @@ }, { "id": "89", + "order": 88, "step": 4, "episode": "18", "title": "Os Momentos", @@ -933,6 +1043,7 @@ }, { "id": "90", + "order": 89, "step": 5, "episode": "18", "title": "A Despedida", @@ -943,6 +1054,7 @@ }, { "id": "91", + "order": 90, "step": 1, "episode": "19", "title": "O Ano Novo", @@ -953,6 +1065,7 @@ }, { "id": "92", + "order": 91, "step": 2, "episode": "19", "title": "As Metas", @@ -963,6 +1076,7 @@ }, { "id": "93", + "order": 92, "step": 3, "episode": "19", "title": "Os Objetivos", @@ -973,6 +1087,7 @@ }, { "id": "94", + "order": 93, "step": 4, "episode": "19", "title": "O Plano", @@ -983,6 +1098,7 @@ }, { "id": "95", + "order": 94, "step": 5, "episode": "19", "title": "A Execução", @@ -993,6 +1109,7 @@ }, { "id": "96", + "order": 95, "step": 1, "episode": "20", "title": "O Desafio", @@ -1003,6 +1120,7 @@ }, { "id": "97", + "order": 96, "step": 2, "episode": "20", "title": "A Preparação", @@ -1013,6 +1131,7 @@ }, { "id": "98", + "order": 97, "step": 3, "episode": "20", "title": "O Enfrentamento", @@ -1023,6 +1142,7 @@ }, { "id": "99", + "order": 98, "step": 4, "episode": "20", "title": "A Superação", @@ -1033,6 +1153,7 @@ }, { "id": "100", + "order": 99, "step": 5, "episode": "20", "title": "A Vitória", diff --git a/package.json b/package.json index 9b54b86..7f8f3d1 100644 --- a/package.json +++ b/package.json @@ -11,16 +11,20 @@ }, "dependencies": { "@dnd-kit/core": "^6.3.1", + "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@headlessui/react": "^2.2.4", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "daisyui": "^5.0.43", "lucide-react": "^0.511.0", "react": "^19.1.0", "react-dom": "^19.1.0", + "react-hot-toast": "^2.5.2", "react-router-dom": "^7.6.1", "tailwind-merge": "^3.3.0", - "tailwindcss": "^4.1.8" + "tailwindcss": "^4.1.8", + "zod": "^3.25.67" }, "devDependencies": { "@eslint/js": "^9.27.0", @@ -35,6 +39,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/pnpm-lock.yaml b/pnpm-lock.yaml index d1a1c5b..208c6d7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: '@dnd-kit/core': specifier: ^6.3.1 version: 6.3.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@dnd-kit/sortable': + specifier: ^10.0.0 + version: 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0) '@dnd-kit/utilities': specifier: ^3.2.2 version: 3.2.2(react@19.1.0) @@ -23,6 +26,9 @@ importers: clsx: specifier: ^2.1.1 version: 2.1.1 + daisyui: + specifier: ^5.0.43 + version: 5.0.43 lucide-react: specifier: ^0.511.0 version: 0.511.0(react@19.1.0) @@ -32,6 +38,9 @@ importers: react-dom: specifier: ^19.1.0 version: 19.1.0(react@19.1.0) + react-hot-toast: + specifier: ^2.5.2 + version: 2.5.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0) react-router-dom: specifier: ^7.6.1 version: 7.6.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -41,6 +50,9 @@ importers: tailwindcss: specifier: ^4.1.8 version: 4.1.8 + zod: + specifier: ^3.25.67 + version: 3.25.67 devDependencies: '@eslint/js': specifier: ^9.27.0 @@ -78,6 +90,9 @@ importers: globals: specifier: ^16.2.0 version: 16.2.0 + json-server: + specifier: 1.0.0-beta.3 + version: 1.0.0-beta.3 typescript: specifier: ~5.8.3 version: 5.8.3 @@ -184,6 +199,12 @@ packages: react: '>=16.8.0' react-dom: '>=16.8.0' + '@dnd-kit/sortable@10.0.0': + resolution: {integrity: sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==} + peerDependencies: + '@dnd-kit/core': ^6.3.0 + react: '>=16.8.0' + '@dnd-kit/utilities@3.2.2': resolution: {integrity: sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==} peerDependencies: @@ -463,6 +484,9 @@ packages: resolution: {integrity: sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@react-aria/focus@3.20.3': resolution: {integrity: sha512-rR5uZUMSY4xLHmpK/I8bP1V6vUNHFo33gTvrvNUsAKKqvMfa7R2nu5A6v97dr5g6tVH6xzpdkPsOJCWh90H2cw==} peerDependencies: @@ -708,6 +732,82 @@ packages: '@tanstack/virtual-core@3.13.9': resolution: {integrity: sha512-3jztt0jpaoJO5TARe2WIHC1UQC3VMLAFUW5mmMo0yrkwtDB2AQP0+sh10BVUpWrnvHjSLvzFizydtEGLCJKFoQ==} + '@tinyhttp/accepts@2.2.3': + resolution: {integrity: sha512-9pQN6pJAJOU3McmdJWTcyq7LLFW8Lj5q+DadyKcvp+sxMkEpktKX5sbfJgJuOvjk6+1xWl7pe0YL1US1vaO/1w==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/app@2.5.2': + resolution: {integrity: sha512-DcB3Y8GQppLQlO2VxRYF7LzTEAoZb+VRQXuIsErcu2fNaM1xdx6NQZDso5rlZUiaeg6KYYRfU34N4XkZbv6jSA==} + engines: {node: '>=14.21.3'} + + '@tinyhttp/content-disposition@2.2.2': + resolution: {integrity: sha512-crXw1txzrS36huQOyQGYFvhTeLeG0Si1xu+/l6kXUVYpE0TjFjEZRqTbuadQLfKGZ0jaI+jJoRyqaWwxOSHW2g==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/content-type@0.1.4': + resolution: {integrity: sha512-dl6f3SHIJPYbhsW1oXdrqOmLSQF/Ctlv3JnNfXAE22kIP7FosqJHxkz/qj2gv465prG8ODKH5KEyhBkvwrueKQ==} + engines: {node: '>=12.4'} + + '@tinyhttp/cookie-signature@2.1.1': + resolution: {integrity: sha512-VDsSMY5OJfQJIAtUgeQYhqMPSZptehFSfvEEtxr+4nldPA8IImlp3QVcOVuK985g4AFR4Hl1sCbWCXoqBnVWnw==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/cookie@2.1.1': + resolution: {integrity: sha512-h/kL9jY0e0Dvad+/QU3efKZww0aTvZJslaHj3JTPmIPC9Oan9+kYqmh3M6L5JUQRuTJYFK2nzgL2iJtH2S+6dA==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/cors@2.0.1': + resolution: {integrity: sha512-qrmo6WJuaiCzKWagv2yA/kw6hIISfF/hOqPWwmI6w0o8apeTMmRN3DoCFvQ/wNVuWVdU5J4KU7OX8aaSOEq51A==} + engines: {node: '>=12.20 || 14.x || >=16'} + + '@tinyhttp/encode-url@2.1.1': + resolution: {integrity: sha512-AhY+JqdZ56qV77tzrBm0qThXORbsVjs/IOPgGCS7x/wWnsa/Bx30zDUU/jPAUcSzNOzt860x9fhdGpzdqbUeUw==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/etag@2.1.2': + resolution: {integrity: sha512-j80fPKimGqdmMh6962y+BtQsnYPVCzZfJw0HXjyH70VaJBHLKGF+iYhcKqzI3yef6QBNa8DKIPsbEYpuwApXTw==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/forwarded@2.1.2': + resolution: {integrity: sha512-9H/eulJ68ElY/+zYpTpNhZ7vxGV+cnwaR6+oQSm7bVgZMyuQfgROW/qvZuhmgDTIxnGMXst+Ba4ij6w6Krcs3w==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/logger@2.1.0': + resolution: {integrity: sha512-Ma1fJ9CwUbn9r61/4HW6+nflsVoslpOnCrfQ6UeZq7GGIgwLzofms3HoSVG7M+AyRMJpxlfcDdbH5oFVroDMKA==} + engines: {node: '>=14.18 || >=16.20'} + + '@tinyhttp/proxy-addr@2.2.1': + resolution: {integrity: sha512-BicqMqVI91hHq2BQmnqJUh0FQUnx7DncwSGgu2ghlh+JZG2rHK2ZN/rXkfhrx1rrUw6hnd0L36O8GPMh01+dDQ==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/req@2.2.5': + resolution: {integrity: sha512-trfsXwtmsNjMcGKcLJ+45h912kLRqBQCQD06ams3Tq0kf4gHLxjHjoYOC1Z9yGjOn81XllRx8wqvnvr+Kbe3gw==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/res@2.2.5': + resolution: {integrity: sha512-yBsqjWygpuKAVz4moWlP4hqzwiDDqfrn2mA0wviJAcgvGiyOErtlQwXY7aj3aPiCpURvxvEFO//Gdy6yV+xEpA==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/router@2.2.3': + resolution: {integrity: sha512-O0MQqWV3Vpg/uXsMYg19XsIgOhwjyhTYWh51Qng7bxqXixxx2PEvZWnFjP7c84K7kU/nUX41KpkEBTLnznk9/Q==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/send@2.2.3': + resolution: {integrity: sha512-o4cVHHGQ8WjVBS8UT0EE/2WnjoybrfXikHwsRoNlG1pfrC/Sd01u1N4Te8cOd/9aNGLr4mGxWb5qTm2RRtEi7g==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/type-is@2.2.4': + resolution: {integrity: sha512-7F328NheridwjIfefBB2j1PEcKKABpADgv7aCJaE8x8EON77ZFrAkI3Rir7pGjopV7V9MBmW88xUQigBEX2rmQ==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/url@2.1.1': + resolution: {integrity: sha512-POJeq2GQ5jI7Zrdmj22JqOijB5/GeX+LEX7DUdml1hUnGbJOTWDx7zf2b5cCERj7RoXL67zTgyzVblBJC+NJWg==} + engines: {node: '>=12.20.0'} + + '@tinyhttp/vary@0.1.3': + resolution: {integrity: sha512-SoL83sQXAGiHN1jm2VwLUWQSQeDAAl1ywOm6T0b0Cg1CZhVsjoiZadmjhxF6FHCCY7OHHVaLnTgSMxTPIDLxMg==} + engines: {node: '>=12.20'} + '@trivago/prettier-plugin-sort-imports@5.2.2': resolution: {integrity: sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==} engines: {node: '>18.12'} @@ -909,6 +1009,14 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chalk@5.4.1: + resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + chownr@3.0.0: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} @@ -927,6 +1035,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -944,6 +1055,9 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + daisyui@5.0.43: + resolution: {integrity: sha512-2pshHJ73vetSpsbAyaOncGnNYL0mwvgseS1EWy1I9Qpw8D11OuBoDNIWrPIME4UFcq2xuff3A9x+eXbuFR9fUQ==} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -956,6 +1070,9 @@ packages: resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} engines: {node: '>= 0.4'} + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -992,6 +1109,10 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} + dot-prop@9.0.0: + resolution: {integrity: sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==} + engines: {node: '>=18'} + dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} @@ -1015,6 +1136,10 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-escape-html@0.1.1: + resolution: {integrity: sha512-yUx1o+8RsG7UlszmYPtks+dm6Lho2m8lgHMOsLJQsFI0R8XwUJwiMhM1M4E/S8QLeGyf6MkDV/pWgjQ0tdTSyQ==} + engines: {node: '>=12.x'} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -1145,6 +1270,10 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + eta@3.5.0: + resolution: {integrity: sha512-e3x3FBvGzeCIHhF+zhK8FZA2vC5uFn6b4HJjegUbIWrDb4mJ7JjTGMJY9VGIbRVpmSwHopNiaJibhjIr+HfLug==} + engines: {node: '>=6.0.0'} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -1250,6 +1379,11 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} + goober@2.1.16: + resolution: {integrity: sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==} + peerDependencies: + csstype: ^3.0.10 + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -1287,6 +1421,13 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + header-range-parser@1.1.3: + resolution: {integrity: sha512-B9zCFt3jH8g09LR1vHL4pcAn8yMEtlSlOUdQemzHMRKMImNIhhszdeosYFfNW0WXKQtXIlWB+O4owHJKvEJYaA==} + engines: {node: '>=12.22.0'} + + http-status-emojis@2.2.0: + resolution: {integrity: sha512-ompKtgwpx8ff0hsbpIB7oE4ax1LXoHmftsHHStMELX56ivG3GhofTX8ZHWlUaFKfGjcGjw6G3rPk7dJRXMmbbg==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1303,10 +1444,18 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + inflection@3.0.2: + resolution: {integrity: sha512-+Bg3+kg+J6JUWn8J6bzFmOWkTQ6L/NHfDRSYU+EVvuKHDxUDHAXgqixHfVlzuBQaPOTac8hn43aPhMNk6rMe3g==} + engines: {node: '>=18.0.0'} + internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} + ipaddr.js@2.2.0: + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} + engines: {node: '>= 10'} + is-array-buffer@3.0.5: resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} engines: {node: '>= 0.4'} @@ -1438,6 +1587,11 @@ packages: json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + json-server@1.0.0-beta.3: + resolution: {integrity: sha512-DwE69Ep5ccwIJZBUIWEENC30Yj8bwr4Ax9W9VoIWAYnB8Sj4ReptscO8/DRHv/nXwVlmb3Bk73Ls86+VZdYkkA==} + engines: {node: '>=18.3'} + hasBin: true + json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} @@ -1531,6 +1685,10 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lowdb@7.0.1: + resolution: {integrity: sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==} + engines: {node: '>=18'} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -1554,6 +1712,15 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + milliparsec@4.0.0: + resolution: {integrity: sha512-/wk9d4Z6/9ZvoEH/6BI4TrTCgmkpZPuSRN/6fI9aUHOfXdNTuj/VhLS7d+NqG26bi6L9YmGXutVYvWC8zQ0qtA==} + engines: {node: '>=20'} + + mime@4.0.4: + resolution: {integrity: sha512-v8yqInVjhXyqP6+Kw4fV3ZzeMRqEW6FotRsKXjRS5VMTNIuXsdRoAvklpoRgSqXm6o9VNH4/C0mgedko9DdLsQ==} + engines: {node: '>=16'} + hasBin: true + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -1577,6 +1744,10 @@ packages: engines: {node: '>=10'} hasBin: true + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1588,6 +1759,10 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} @@ -1690,6 +1865,13 @@ packages: peerDependencies: react: ^19.1.0 + react-hot-toast@2.5.2: + resolution: {integrity: sha512-Tun3BbCxzmXXM7C+NI4qiv6lT0uwGh4oAfeJyNOjYUejTsm35mK9iCaYLGv8cBz9L5YxZLx/2ii7zsIwPtPUdw==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16' + react-dom: '>=16' + react-refresh@0.17.0: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} @@ -1715,6 +1897,10 @@ packages: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -1723,6 +1909,10 @@ packages: resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} engines: {node: '>= 0.4'} + regexparam@2.0.2: + resolution: {integrity: sha512-A1PeDEYMrkLrfyOwv2jwihXbo9qxdGD3atBYQA9JJgreAx8/7rC6IUkWOw2NQlOxLp2wL0ifQbh1HuidDfYA6w==} + engines: {node: '>=8'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1807,10 +1997,22 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + + sort-on@6.1.0: + resolution: {integrity: sha512-WTECP0nYNWO1n2g5bpsV0yZN9cBmZsF8ThHFbOqVN0HBFRoaQZLLEMvMmJlKHNPYQeVngeI5+jJzIfFqOIo1OA==} + engines: {node: '>=18'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + steno@4.0.2: + resolution: {integrity: sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==} + engines: {node: '>=18'} + stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -1872,6 +2074,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + ts-api-utils@2.1.0: resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} @@ -1888,6 +2094,10 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + typed-array-buffer@1.0.3: resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} engines: {node: '>= 0.4'} @@ -2010,6 +2220,9 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + zod@3.25.67: + resolution: {integrity: sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==} + snapshots: '@ampproject/remapping@2.3.0': @@ -2140,6 +2353,13 @@ snapshots: react-dom: 19.1.0(react@19.1.0) tslib: 2.8.1 + '@dnd-kit/sortable@10.0.0(@dnd-kit/core@6.3.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)': + dependencies: + '@dnd-kit/core': 6.3.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@dnd-kit/utilities': 3.2.2(react@19.1.0) + react: 19.1.0 + tslib: 2.8.1 + '@dnd-kit/utilities@3.2.2(react@19.1.0)': dependencies: react: 19.1.0 @@ -2347,6 +2567,8 @@ snapshots: '@pkgr/core@0.2.4': {} + '@polka/url@1.0.0-next.29': {} + '@react-aria/focus@3.20.3(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': dependencies: '@react-aria/interactions': 3.25.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -2543,6 +2765,86 @@ snapshots: '@tanstack/virtual-core@3.13.9': {} + '@tinyhttp/accepts@2.2.3': + dependencies: + mime: 4.0.4 + negotiator: 0.6.4 + + '@tinyhttp/app@2.5.2': + dependencies: + '@tinyhttp/cookie': 2.1.1 + '@tinyhttp/proxy-addr': 2.2.1 + '@tinyhttp/req': 2.2.5 + '@tinyhttp/res': 2.2.5 + '@tinyhttp/router': 2.2.3 + header-range-parser: 1.1.3 + regexparam: 2.0.2 + + '@tinyhttp/content-disposition@2.2.2': {} + + '@tinyhttp/content-type@0.1.4': {} + + '@tinyhttp/cookie-signature@2.1.1': {} + + '@tinyhttp/cookie@2.1.1': {} + + '@tinyhttp/cors@2.0.1': + dependencies: + '@tinyhttp/vary': 0.1.3 + + '@tinyhttp/encode-url@2.1.1': {} + + '@tinyhttp/etag@2.1.2': {} + + '@tinyhttp/forwarded@2.1.2': {} + + '@tinyhttp/logger@2.1.0': + dependencies: + colorette: 2.0.20 + dayjs: 1.11.13 + http-status-emojis: 2.2.0 + + '@tinyhttp/proxy-addr@2.2.1': + dependencies: + '@tinyhttp/forwarded': 2.1.2 + ipaddr.js: 2.2.0 + + '@tinyhttp/req@2.2.5': + dependencies: + '@tinyhttp/accepts': 2.2.3 + '@tinyhttp/type-is': 2.2.4 + '@tinyhttp/url': 2.1.1 + header-range-parser: 1.1.3 + + '@tinyhttp/res@2.2.5': + dependencies: + '@tinyhttp/content-disposition': 2.2.2 + '@tinyhttp/cookie': 2.1.1 + '@tinyhttp/cookie-signature': 2.1.1 + '@tinyhttp/encode-url': 2.1.1 + '@tinyhttp/req': 2.2.5 + '@tinyhttp/send': 2.2.3 + '@tinyhttp/vary': 0.1.3 + es-escape-html: 0.1.1 + mime: 4.0.4 + + '@tinyhttp/router@2.2.3': {} + + '@tinyhttp/send@2.2.3': + dependencies: + '@tinyhttp/content-type': 0.1.4 + '@tinyhttp/etag': 2.1.2 + mime: 4.0.4 + + '@tinyhttp/type-is@2.2.4': + dependencies: + '@tinyhttp/content-type': 0.1.4 + mime: 4.0.4 + + '@tinyhttp/url@2.1.1': {} + + '@tinyhttp/vary@0.1.3': {} + '@trivago/prettier-plugin-sort-imports@5.2.2(prettier@3.5.3)': dependencies: '@babel/generator': 7.27.3 @@ -2815,6 +3117,12 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chalk@5.4.1: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + chownr@3.0.0: {} class-variance-authority@0.7.1: @@ -2829,6 +3137,8 @@ snapshots: color-name@1.1.4: {} + colorette@2.0.20: {} + concat-map@0.0.1: {} convert-source-map@2.0.0: {} @@ -2843,6 +3153,8 @@ snapshots: csstype@3.1.3: {} + daisyui@5.0.43: {} + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -2861,6 +3173,8 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 + dayjs@1.11.13: {} + debug@3.2.7: dependencies: ms: 2.1.3 @@ -2889,6 +3203,10 @@ snapshots: dependencies: esutils: 2.0.3 + dot-prop@9.0.0: + dependencies: + type-fest: 4.41.0 + dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.2 @@ -2963,6 +3281,8 @@ snapshots: es-errors@1.3.0: {} + es-escape-html@0.1.1: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -3147,6 +3467,8 @@ snapshots: esutils@2.0.3: {} + eta@3.5.0: {} + fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -3256,6 +3578,10 @@ snapshots: define-properties: 1.2.1 gopd: 1.2.0 + goober@2.1.16(csstype@3.1.3): + dependencies: + csstype: 3.1.3 + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -3284,6 +3610,10 @@ snapshots: dependencies: function-bind: 1.1.2 + header-range-parser@1.1.3: {} + + http-status-emojis@2.2.0: {} + ignore@5.3.2: {} ignore@7.0.4: {} @@ -3295,12 +3625,16 @@ snapshots: imurmurhash@0.1.4: {} + inflection@3.0.2: {} + internal-slot@1.1.0: dependencies: es-errors: 1.3.0 hasown: 2.0.2 side-channel: 1.1.0 + ipaddr.js@2.2.0: {} + is-array-buffer@3.0.5: dependencies: call-bind: 1.0.8 @@ -3428,6 +3762,22 @@ snapshots: json-schema-traverse@0.4.1: {} + json-server@1.0.0-beta.3: + dependencies: + '@tinyhttp/app': 2.5.2 + '@tinyhttp/cors': 2.0.1 + '@tinyhttp/logger': 2.1.0 + chalk: 5.4.1 + chokidar: 4.0.3 + dot-prop: 9.0.0 + eta: 3.5.0 + inflection: 3.0.2 + json5: 2.2.3 + lowdb: 7.0.1 + milliparsec: 4.0.0 + sirv: 2.0.4 + sort-on: 6.1.0 + json-stable-stringify-without-jsonify@1.0.1: {} json5@1.0.2: @@ -3498,6 +3848,10 @@ snapshots: lodash@4.17.21: {} + lowdb@7.0.1: + dependencies: + steno: 4.0.2 + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -3519,6 +3873,10 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + milliparsec@4.0.0: {} + + mime@4.0.4: {} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -3537,12 +3895,16 @@ snapshots: mkdirp@3.0.1: {} + mrmime@2.0.1: {} + ms@2.1.3: {} nanoid@3.3.11: {} natural-compare@1.4.0: {} + negotiator@0.6.4: {} + node-releases@2.0.19: {} object-inspect@1.13.4: {} @@ -3642,6 +4004,13 @@ snapshots: react: 19.1.0 scheduler: 0.26.0 + react-hot-toast@2.5.2(react-dom@19.1.0(react@19.1.0))(react@19.1.0): + dependencies: + csstype: 3.1.3 + goober: 2.1.16(csstype@3.1.3) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-refresh@0.17.0: {} react-router-dom@7.6.1(react-dom@19.1.0(react@19.1.0))(react@19.1.0): @@ -3660,6 +4029,8 @@ snapshots: react@19.1.0: {} + readdirp@4.1.2: {} + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -3680,6 +4051,8 @@ snapshots: gopd: 1.2.0 set-function-name: 2.0.2 + regexparam@2.0.2: {} + resolve-from@4.0.0: {} resolve@1.22.10: @@ -3803,8 +4176,20 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + + sort-on@6.1.0: + dependencies: + dot-prop: 9.0.0 + source-map-js@1.2.1: {} + steno@4.0.2: {} + stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -3873,6 +4258,8 @@ snapshots: dependencies: is-number: 7.0.0 + totalist@3.0.1: {} + ts-api-utils@2.1.0(typescript@5.8.3): dependencies: typescript: 5.8.3 @@ -3890,6 +4277,8 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-fest@4.41.0: {} + typed-array-buffer@1.0.3: dependencies: call-bound: 1.0.4 @@ -4021,3 +4410,5 @@ snapshots: yallist@5.0.0: {} yocto-queue@0.1.0: {} + + zod@3.25.67: {} diff --git a/src/App.tsx b/src/App.tsx index c0ff118..6847825 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,13 +1,18 @@ -import {ProductionProvider} from "./contexts/production" -import Routes from "./routes" -import "./styles/global.css" +import { Toast } from './components/atoms'; +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/atoms/Button/@types/index.ts b/src/components/atoms/Button/@types/index.ts new file mode 100644 index 0000000..602826f --- /dev/null +++ b/src/components/atoms/Button/@types/index.ts @@ -0,0 +1,9 @@ +import { type VariantProps } from 'class-variance-authority'; + +import { type buttonVariants } from '../variants'; + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} diff --git a/src/components/atoms/Button/index.tsx b/src/components/atoms/Button/index.tsx new file mode 100644 index 0000000..1f21e05 --- /dev/null +++ b/src/components/atoms/Button/index.tsx @@ -0,0 +1,20 @@ +import { forwardRef } from 'react'; + +import { Button as HeadlessButton } from '@headlessui/react'; + +import { cn } from '../../../utils/cn'; +import { type ButtonProps } from './@types'; +import { buttonVariants } from './variants'; + +const Button = forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? HeadlessButton : 'button'; + return ( + + ); + }, +); + +Button.displayName = 'Button'; + +export { Button }; diff --git a/src/components/button/index.tsx b/src/components/atoms/Button/variants.ts similarity index 57% rename from src/components/button/index.tsx rename to src/components/atoms/Button/variants.ts index 4fcc7d0..1634472 100644 --- a/src/components/button/index.tsx +++ b/src/components/atoms/Button/variants.ts @@ -1,12 +1,7 @@ -import {forwardRef} from 'react'; +import { cva } from 'class-variance-authority'; -import {Button as HeadlessButton} from '@headlessui/react'; -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', +export 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 cursor-pointer', { variants: { variant: { @@ -28,22 +23,5 @@ const buttonVariants = cva( variant: 'default', size: 'default', }, - } -); - -interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { - asChild?: boolean; -} - -const Button = forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? HeadlessButton : 'button'; - return ( - ; - ); }, ); - -Button.displayName = 'Button'; - -export { Button }; diff --git a/src/components/atoms/Input/@types/index.ts b/src/components/atoms/Input/@types/index.ts new file mode 100644 index 0000000..f59483d --- /dev/null +++ b/src/components/atoms/Input/@types/index.ts @@ -0,0 +1,9 @@ +import { type VariantProps } from 'class-variance-authority'; + +import { type inputVariants } from '../variants'; + +export interface InputProps + extends Omit, 'size'>, + VariantProps { + error?: boolean; +} diff --git a/src/components/atoms/Input/index.tsx b/src/components/atoms/Input/index.tsx new file mode 100644 index 0000000..a2c6af9 --- /dev/null +++ b/src/components/atoms/Input/index.tsx @@ -0,0 +1,44 @@ +import { forwardRef } from 'react'; + +import { cva } from 'class-variance-authority'; + +import { cn } from '../../../utils/cn'; +import { type InputProps } from './@types'; + +const inputVariants = cva( + 'flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', + { + variants: { + variant: { + default: 'border-input', + error: 'border-destructive focus-visible:ring-destructive', + }, + inputSize: { + default: 'h-10', + sm: 'h-9 px-2', + lg: 'h-11 px-4', + }, + }, + defaultVariants: { + variant: 'default', + inputSize: 'default', + }, + }, +); + +const Input = forwardRef( + ({ className, variant, inputSize, error, type, ...props }, ref) => { + return ( + + ); + }, +); + +Input.displayName = 'Input'; + +export { Input }; diff --git a/src/components/atoms/Input/variants.ts b/src/components/atoms/Input/variants.ts new file mode 100644 index 0000000..c4d3203 --- /dev/null +++ b/src/components/atoms/Input/variants.ts @@ -0,0 +1,22 @@ +import { cva } from 'class-variance-authority'; + +export const inputVariants = cva( + 'flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50', + { + variants: { + variant: { + default: 'border-input', + error: 'border-destructive focus-visible:ring-destructive', + }, + inputSize: { + default: 'h-10', + sm: 'h-9 px-2', + lg: 'h-11 px-4', + }, + }, + defaultVariants: { + variant: 'default', + inputSize: 'default', + }, + }, +); diff --git a/src/components/title/index.tsx b/src/components/atoms/Title/index.tsx similarity index 67% rename from src/components/title/index.tsx rename to src/components/atoms/Title/index.tsx index bdf3246..dd18a07 100644 --- a/src/components/title/index.tsx +++ b/src/components/atoms/Title/index.tsx @@ -1,4 +1,4 @@ -import { useProduction } from '../../hooks/useProduction'; +import { useProduction } from '../../../hooks/useProduction'; const Title = () => { const { selectedProduction } = useProduction(); @@ -6,4 +6,4 @@ const Title = () => { return

{selectedProduction?.name}

; }; -export default Title; +export { Title }; diff --git a/src/components/atoms/Toast/index.tsx b/src/components/atoms/Toast/index.tsx new file mode 100644 index 0000000..1952760 --- /dev/null +++ b/src/components/atoms/Toast/index.tsx @@ -0,0 +1,28 @@ +import { Toaster } from 'react-hot-toast'; + +export function Toast() { + return ( + + ); +} diff --git a/src/components/atoms/index.ts b/src/components/atoms/index.ts new file mode 100644 index 0000000..b5c6be9 --- /dev/null +++ b/src/components/atoms/index.ts @@ -0,0 +1,6 @@ +import { Button } from './Button'; +import { Input } from './Input'; +import { Title } from './Title'; +import { Toast } from './Toast'; + +export { Input, Title, Toast, Button }; diff --git a/src/components/card/index.tsx b/src/components/card/index.tsx deleted file mode 100644 index 53c4f4b..0000000 --- a/src/components/card/index.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import {type ReactNode} from "react" - -interface QuickLink { - label: string - count?: number - onClick?: () => void -} - -interface CardFooter { - label: string - onClick?: () => void -} - -interface CardProps { - icon: ReactNode - title: string - subtitle?: string - quickLinks?: QuickLink[] - footer?: CardFooter - className?: string -} - -export function Card({icon, title, subtitle, quickLinks = [], footer, className = ""}: CardProps) { - return ( -
-
-
{icon}
-
-
- {title} -
- {subtitle && ( -
- {subtitle} -
- )} -
-
- {quickLinks.length > 0 && ( -
-
Links rápidos
-
    - {quickLinks.map(link => ( -
  • - {link.label} - {link.count !== undefined && ( - - {link.count} - - )} -
  • - ))} -
-
- )} - {footer &&
} - {footer && ( - - )} -
- ) -} diff --git a/src/components/column/index.tsx b/src/components/column/index.tsx deleted file mode 100644 index ff57656..0000000 --- a/src/components/column/index.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { type ReactNode, useEffect, useState } from 'react'; - -import { useDroppable } from '@dnd-kit/core'; - -import { cn } from '../../utils/cn'; - -interface ColumnProps { - id: string; - step: number; - label: string; - count?: number; - description?: string; - children?: ReactNode; -} - -export function Column({ id, step, label, count, description, children }: ColumnProps) { - const [disabled, setDisabled] = useState(false); - - const { setNodeRef, isOver, active, over } = useDroppable({ - id, - data: { - step, - }, - disabled, - }); - - useEffect(() => { - if (!over) { - setDisabled(false); - return; - } - - const actual = active?.data.current?.step; - - if (actual) { - const isDisabled = step === actual; - setDisabled(isDisabled); - } else { - setDisabled(false); - } - }, [active, over, setDisabled, step]); - - return ( -
-
-
- {label} - {typeof count === 'number' && ( - - {count} - - )} -
-
- {description &&
{description}
} -
{children}
-
- ); -} diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx deleted file mode 100644 index 58a2892..0000000 --- a/src/components/header/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import {Button} from "../button" -import {Input} from "../input" - -export function Header() { - return ( -
-
-

StudioFlow

-
- -
- - -
- -
- John Doe -
- JD -
-
-
- ) -} diff --git a/src/components/input/index.tsx b/src/components/input/index.tsx deleted file mode 100644 index eb1130d..0000000 --- a/src/components/input/index.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import {forwardRef} from "react" - -import {type VariantProps, cva} from "class-variance-authority" - -import {cn} from "../../utils/cn" - -const inputVariants = cva( - "flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", - { - variants: { - variant: { - default: "border-input", - error: "border-destructive focus-visible:ring-destructive" - }, - inputSize: { - default: "h-10", - sm: "h-9 px-2", - lg: "h-11 px-4" - } - }, - defaultVariants: { - variant: "default", - inputSize: "default" - } - } -) - -interface InputProps extends Omit, VariantProps { - error?: boolean -} - -const Input = forwardRef( - ({className, variant, inputSize, error, type, ...props}, ref) => { - return ( - - ) - } -) - -Input.displayName = "Input" - -export {Input} diff --git a/src/components/layout/index.tsx b/src/components/layout/index.tsx deleted file mode 100644 index ef5b637..0000000 --- a/src/components/layout/index.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import {Outlet} from "react-router-dom" - -import {Header} from "../header" -import {Sidebar} from "../sidebar" - -export function Layout() { - return ( -
-
-
- -
- -
-
-
- ) -} diff --git a/src/components/modal/index.tsx b/src/components/modal/index.tsx deleted file mode 100644 index 94114dd..0000000 --- a/src/components/modal/index.tsx +++ /dev/null @@ -1,197 +0,0 @@ -import {Fragment, useState} from "react" - -import {Dialog, DialogPanel, DialogTitle, Transition, TransitionChild} from "@headlessui/react" -import {XIcon} from "lucide-react" - -import {type Scene as SceneDetails} from "../../reducers/scenes" - -interface ModalProps { - 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 handleChange = (field: keyof SceneDetails, value: string | number) => { - 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 - } - } - - setEditedScene({...editedScene, [field]: value}) - } - - const handleSave = async () => { - if (!editedScene || !onUpdate) return - - setIsSaving(true) - - await fetch(`${import.meta.env.VITE_API_URL}/scenes/${editedScene.id}`, { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify({ - ...editedScene, - updatedAt: new Date().toISOString(), - version: Math.random() - }) - }) - - onUpdate(editedScene) - onClose() - setIsSaving(false) - } - - return ( - - - -
- - -
-
- - -
- - Detalhes da Cena - - -
- - {editedScene ? ( -
-
-

Título

- 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' - /> -
- -
-

Descrição

-