├── src ├── vite-env.d.ts ├── http │ ├── types │ │ ├── create-room-response.ts │ │ ├── create-question-request.ts │ │ ├── create-room-request.ts │ │ ├── create-question-response.ts │ │ ├── get-rooms-response.ts │ │ └── get-room-questions-response.ts │ ├── use-rooms.ts │ ├── use-room-questions.ts │ ├── use-create-room.ts │ └── use-create-question.ts ├── lib │ ├── utils.ts │ └── dayjs.ts ├── main.tsx ├── pages │ ├── create-room.tsx │ ├── room.tsx │ └── record-room-audio.tsx ├── components │ ├── ui │ │ ├── label.tsx │ │ ├── textarea.tsx │ │ ├── input.tsx │ │ ├── badge.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ └── form.tsx │ ├── question-list.tsx │ ├── room-list.tsx │ ├── question-item.tsx │ ├── question-form.tsx │ └── create-room-form.tsx ├── app.tsx └── index.css ├── biome.jsonc ├── .gitignore ├── index.html ├── tsconfig.json ├── vite.config.ts ├── components.json ├── tsconfig.node.json ├── tsconfig.app.json ├── package.json └── README.md /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/http/types/create-room-response.ts: -------------------------------------------------------------------------------- 1 | export type CreateRoomResponse = { 2 | roomId: string 3 | } 4 | -------------------------------------------------------------------------------- /src/http/types/create-question-request.ts: -------------------------------------------------------------------------------- 1 | export type CreateQuestionRequest = { 2 | question: string 3 | } 4 | -------------------------------------------------------------------------------- /src/http/types/create-room-request.ts: -------------------------------------------------------------------------------- 1 | export type CreateRoomRequest = { 2 | name: string 3 | description: string 4 | } 5 | -------------------------------------------------------------------------------- /src/http/types/create-question-response.ts: -------------------------------------------------------------------------------- 1 | export type CreateQuestionResponse = { 2 | questionId: string 3 | answer: string | null 4 | } 5 | -------------------------------------------------------------------------------- /src/http/types/get-rooms-response.ts: -------------------------------------------------------------------------------- 1 | export type GetRoomsResponse = Array<{ 2 | id: string 3 | name: string 4 | questionsCount: number 5 | createdAt: string 6 | }> 7 | -------------------------------------------------------------------------------- /src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /src/lib/dayjs.ts: -------------------------------------------------------------------------------- 1 | import lib from 'dayjs' 2 | import 'dayjs/locale/pt-BR' 3 | import relativeTime from 'dayjs/plugin/relativeTime' 4 | 5 | lib.locale('pt-BR') 6 | lib.extend(relativeTime) 7 | 8 | export const dayjs = lib 9 | -------------------------------------------------------------------------------- /src/http/types/get-room-questions-response.ts: -------------------------------------------------------------------------------- 1 | export type GetRoomQuestionsResponse = Array<{ 2 | id: string 3 | question: string 4 | answer: string | null 5 | createdAt: string 6 | isGeneratingAnswer?: boolean 7 | }> 8 | -------------------------------------------------------------------------------- /biome.jsonc: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/2.0.5/schema.json", 3 | "extends": [ 4 | "ultracite" 5 | ], 6 | "javascript": { 7 | "formatter": { 8 | "semicolons": "asNeeded" 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import './index.css' 2 | 3 | import { StrictMode } from 'react' 4 | import { createRoot } from 'react-dom/client' 5 | import { App } from './app' 6 | 7 | // biome-ignore lint/style/noNonNullAssertion: mandatory by React 8 | createRoot(document.getElementById('root')!).render( 9 | 10 | 11 | 12 | ) 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Let me Ask 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.app.json" 6 | }, 7 | { 8 | "path": "./tsconfig.node.json" 9 | } 10 | ], 11 | "compilerOptions": { 12 | "strictNullChecks": true, 13 | "baseUrl": ".", 14 | "paths": { 15 | "@/*": [ 16 | "./src/*" 17 | ] 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path' 2 | import tailwindcss from '@tailwindcss/vite' 3 | import react from '@vitejs/plugin-react' 4 | import { defineConfig } from 'vite' 5 | 6 | export default defineConfig({ 7 | plugins: [react(), tailwindcss()], 8 | resolve: { 9 | alias: { 10 | '@': path.resolve(__dirname, './src'), 11 | }, 12 | }, 13 | }) 14 | -------------------------------------------------------------------------------- /src/http/use-rooms.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from '@tanstack/react-query' 2 | import type { GetRoomsResponse } from './types/get-rooms-response' 3 | 4 | export function useRooms() { 5 | return useQuery({ 6 | queryKey: ['get-rooms'], 7 | queryFn: async () => { 8 | const response = await fetch('http://localhost:3333/rooms') 9 | const result: GetRoomsResponse = await response.json() 10 | 11 | return result 12 | }, 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /src/pages/create-room.tsx: -------------------------------------------------------------------------------- 1 | import { CreateRoomForm } from '@/components/create-room-form' 2 | import { RoomList } from '@/components/room-list' 3 | 4 | export function CreateRoom() { 5 | return ( 6 |
7 |
8 |
9 | 10 | 11 |
12 |
13 |
14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "src/index.css", 9 | "baseColor": "zinc", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /src/http/use-room-questions.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from '@tanstack/react-query' 2 | import type { GetRoomQuestionsResponse } from './types/get-room-questions-response' 3 | 4 | export function useRoomQuestions(roomId: string) { 5 | return useQuery({ 6 | queryKey: ['get-questions', roomId], 7 | queryFn: async () => { 8 | const response = await fetch( 9 | `http://localhost:3333/rooms/${roomId}/questions` 10 | ) 11 | const result: GetRoomQuestionsResponse = await response.json() 12 | 13 | return result 14 | }, 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as LabelPrimitive from "@radix-ui/react-label" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | function Label({ 9 | className, 10 | ...props 11 | }: React.ComponentProps) { 12 | return ( 13 | 21 | ) 22 | } 23 | 24 | export { Label } 25 | -------------------------------------------------------------------------------- /src/components/question-list.tsx: -------------------------------------------------------------------------------- 1 | import { useRoomQuestions } from '@/http/use-room-questions' 2 | import { QuestionItem } from './question-item' 3 | 4 | interface QuestionListProps { 5 | roomId: string 6 | } 7 | 8 | export function QuestionList(props: QuestionListProps) { 9 | const { data } = useRoomQuestions(props.roomId) 10 | 11 | return ( 12 |
13 |
14 |

15 | Perguntas & Respostas 16 |

17 |
18 | 19 | {data?.map((question) => { 20 | return 21 | })} 22 |
23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2023", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "verbatimModuleSyntax": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "erasableSyntaxOnly": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "noUncheckedSideEffectImports": true 23 | }, 24 | "include": ["vite.config.ts"] 25 | } 26 | -------------------------------------------------------------------------------- /src/app.tsx: -------------------------------------------------------------------------------- 1 | import { QueryClient, QueryClientProvider } from '@tanstack/react-query' 2 | import { BrowserRouter, Route, Routes } from 'react-router-dom' 3 | import { CreateRoom } from './pages/create-room' 4 | import { RecordRoomAudio } from './pages/record-room-audio' 5 | import { Room } from './pages/room' 6 | 7 | const queryClient = new QueryClient() 8 | 9 | export function App() { 10 | return ( 11 | 12 | 13 | 14 | } index /> 15 | } path="/room/:roomId" /> 16 | } path="/room/:roomId/audio" /> 17 | 18 | 19 | 20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import type * as React from 'react' 2 | 3 | import { cn } from '@/lib/utils' 4 | 5 | function Textarea({ className, ...props }: React.ComponentProps<'textarea'>) { 6 | return ( 7 |