diff --git a/bun.lock b/bun.lock index 2cbace6..82ebd35 100644 --- a/bun.lock +++ b/bun.lock @@ -20,6 +20,7 @@ "next": "^14.2.25", "react": "19.0.0", "react-dom": "19.0.0", + "react-dropzone": "^14.3.8", "react-icons": "^5.5.0", "react-markdown": "^10.1.0", "sharp": "^0.33.5", @@ -416,6 +417,8 @@ "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], + "attr-accept": ["attr-accept@2.2.5", "", {}, "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ=="], + "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], "axe-core": ["axe-core@4.10.3", "", {}, "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg=="], @@ -600,6 +603,8 @@ "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + "file-selector": ["file-selector@2.1.2", "", { "dependencies": { "tslib": "^2.7.0" } }, "sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig=="], + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="], @@ -956,6 +961,8 @@ "react-dom": ["react-dom@19.0.0", "", { "dependencies": { "scheduler": "^0.25.0" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ=="], + "react-dropzone": ["react-dropzone@14.3.8", "", { "dependencies": { "attr-accept": "^2.2.4", "file-selector": "^2.1.0", "prop-types": "^15.8.1" }, "peerDependencies": { "react": ">= 16.8 || 18.0.0" } }, "sha512-sBgODnq+lcA4P296DY4wacOZz3JFpD99fp+hb//iBO2HHnyeZU3FwWyXJ6salNpqQdsZrgMrotuko/BdJMV8Ug=="], + "react-fast-compare": ["react-fast-compare@3.2.2", "", {}, "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="], "react-focus-lock": ["react-focus-lock@2.13.6", "", { "dependencies": { "@babel/runtime": "^7.0.0", "focus-lock": "^1.3.6", "prop-types": "^15.6.2", "react-clientside-effect": "^1.2.7", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ehylFFWyYtBKXjAO9+3v8d0i+cnc1trGS0vlTGhzFW1vbFXVUTmR8s2tt/ZQG8x5hElg6rhENlLG1H3EZK0Llg=="], @@ -1204,6 +1211,8 @@ "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "file-selector/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], diff --git a/package.json b/package.json index 5b5ba2d..1457f83 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "next": "^14.2.25", "react": "19.0.0", "react-dom": "19.0.0", + "react-dropzone": "^14.3.8", "react-icons": "^5.5.0", "react-markdown": "^10.1.0", "sharp": "^0.33.5", @@ -48,4 +49,4 @@ "trustedDependencies": [ "@biomejs/biome" ] -} \ No newline at end of file +} diff --git a/src/components/general/ClassroomCard.tsx b/src/components/general/ClassroomCard.tsx index cb80996..7833759 100644 --- a/src/components/general/ClassroomCard.tsx +++ b/src/components/general/ClassroomCard.tsx @@ -48,7 +48,9 @@ export default function ClassroomCard({ item }: Readonly<{ item: IClassroom }>) - {item.memberCount} estudiantes + + {item.memberCount === 1 ? 'Sin ' : item.memberCount - 1} estudiantes + + + + + ))} + + + )} + + {!isProfessor && isAssignment && ( + + + Enviar Tarea + + {hasSubmitted ? ( + + ¡Tu tarea ha sido enviada! El profesor la revisará pronto. + + ) : ( + + + + + + - {resource.type === 'file' ? 'Descargar' : 'Abrir'} - - - - - ))} - - - )} + {isDragAccept + ? 'Suelta para subir los archivos' + : isDragReject + ? 'Algunos archivos no son válidos' + : isDragActive + ? 'Suelta los archivos aquí' + : 'Arrastra archivos aquí o haz clic para seleccionar'} + + + Máximo 5 archivos, 10MB por archivo + + + + + {files.length > 0 && ( + + + Archivos adjuntos: + + {files.map((file, index) => ( + + + {file.name} ({(file.size / 1024 / 1024).toFixed(2)}MB) + + } + size='sm' + variant='ghost' + colorScheme='red' + onClick={(e) => { + e.stopPropagation(); + removeFile(index); + }} + /> + + ))} + + )} + + setComment(e.target.value)} + bg='brand.dark.800' + border='1px solid' + borderColor='brand.dark.700' + _hover={{ borderColor: 'brand.primary.500' }} + _focus={{ + borderColor: 'brand.primary.500', + boxShadow: '0 0 0 1px var(--chakra-colors-brand-primary-500)' + }} + /> + + + + )} + + )} + diff --git a/src/components/screens/ClassScreen.tsx b/src/components/screens/ClassScreen.tsx index 0ac1836..54cd382 100644 --- a/src/components/screens/ClassScreen.tsx +++ b/src/components/screens/ClassScreen.tsx @@ -2,6 +2,7 @@ import { api } from '@/api/api'; import { CDN_URL } from '@/constants/constants'; +import { authAtom } from '@/store/auth'; import type { IActivity } from '@/types/IActivity'; import type { IClassroom } from '@/types/IClassroomCard'; import type { IUser } from '@/types/IUser'; @@ -27,6 +28,7 @@ import { useDisclosure, useToast } from '@chakra-ui/react'; +import { useAtom } from 'jotai'; import { useRouter } from 'next/navigation'; import { useEffect, useState } from 'react'; import { FiCode, FiFileText, FiPlus, FiUsers } from 'react-icons/fi'; @@ -43,6 +45,7 @@ export default function ClassScreen({ id }: Readonly<{ id: string }>) { const [isMembersLoading, setIsMembersLoading] = useState(false); const { isOpen, onOpen, onClose } = useDisclosure(); const toast = useToast(); + const [auth] = useAtom(authAtom); useEffect(() => { const fetchData = async () => { @@ -56,7 +59,7 @@ export default function ClassScreen({ id }: Readonly<{ id: string }>) { setClassroom(classroomData); setClassActivities(activitiesData); setProfessor(professorData); - } catch (error) { + } catch { toast({ title: 'Error', description: 'No se pudo cargar la información de la clase', @@ -84,7 +87,7 @@ export default function ClassScreen({ id }: Readonly<{ id: string }>) { try { const members = await api.classroom.getMembers(id); setClassMembers(members); - } catch (error) { + } catch { toast({ title: 'Error', description: 'No se pudo cargar la lista de estudiantes', @@ -152,12 +155,16 @@ export default function ClassScreen({ id }: Readonly<{ id: string }>) { - {classroom.memberCount} estudiantes - - - - Código: {classroom.code} + + {classroom.memberCount === 1 ? 'Sin ' : classroom.memberCount - 1} estudiantes + + {classroom.owner === auth.user?.id && ( + + + Código: {classroom.code} + + )} @@ -201,7 +208,7 @@ export default function ClassScreen({ id }: Readonly<{ id: string }>) { > - Estudiantes + Miembros @@ -263,6 +270,41 @@ export default function ClassScreen({ id }: Readonly<{ id: string }>) { + {professor && ( + <> + + Profesor + + + + + + {professor.username} + + Profesor + + + + + + )} Estudiantes @@ -279,32 +321,28 @@ export default function ClassScreen({ id }: Readonly<{ id: string }>) { }} gap={4} > - {classMembers.map((member) => ( - - - - {member.username} - {member.id === classroom.owner ? ( - - Profesor - - ) : ( + {classMembers + .filter((m) => m.id !== classroom.owner) + .map((member) => ( + + + + {member.username} Estudiante - )} - - - ))} + + + ))} )}