Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@
"pnpm": {
"overrides": {
"glob": "^10.5.0",
"systeminformation": ">=5.27.14"
"systeminformation": ">=5.27.14",
"qs": ">=6.14.1"
}
},
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
Expand Down
9 changes: 5 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion src/api/apiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ apiClient.interceptors.response.use(
const newToken = data.data.token;

localStorage.setItem(TOKEN_STORAGE_KEY, newToken);
apiClient.defaults.headers.common['Authorization'] = `Bearer ${newToken}`;

processQueue(null, newToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ import {
useGetPendingRequests,
useProcessJoinRequest,
} from '../../../hooks/useJoinRequests';
import {
getProfessorName,
getProfessorEmail,
getProfessorProfilePicture,
getProfessorInitials,
} from '../../../lib/professor';
import { Professor } from '../../../models/Professor';

interface ManageInstitutionSectionProps {
institution: Institution;
Expand Down Expand Up @@ -142,25 +137,28 @@ export default function ManageInstitutionSection({
</p>
</div>
) : (
pendingRequests.map((req) => (
pendingRequests.map((req) => {
const profInstance = new Professor(req.professor);

return (
<div key={req.id} className="p-3 border rounded-lg bg-slate-50">
<div className="flex items-center justify-between gap-3">
<div className="flex items-center gap-3 flex-1 min-w-0">
<Avatar className="h-10 w-10 flex-shrink-0">
<AvatarImage
src={getProfessorProfilePicture(req.professor)}
alt={getProfessorName(req.professor)}
src={profInstance.profilePicture}
alt={profInstance.fullName}
/>
<AvatarFallback className="bg-slate-400 text-white font-semibold">
{getProfessorInitials(req.professor)}
{profInstance.initials}
</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<p className="font-medium text-slate-800 truncate">
{getProfessorName(req.professor)}
{profInstance.fullName}
</p>
<p className="text-sm text-slate-600 truncate">
{getProfessorEmail(req.professor) ||
{profInstance.email ||
'Email no disponible'}
</p>
</div>
Expand Down Expand Up @@ -192,8 +190,8 @@ export default function ManageInstitutionSection({
</div>
</div>
</div>
))
)}
)}
))}
</div>
</div>

Expand Down Expand Up @@ -231,7 +229,9 @@ export default function ManageInstitutionSection({
</div>
)}
{otherProfessors.length > 0 ? (
otherProfessors.map((professor) => (
otherProfessors.map((professor) => {
const otherProfessorsInstance = new Professor(professor);
return (
<div
key={professor.id}
className="border rounded-lg p-3 hover:bg-slate-50"
Expand All @@ -240,19 +240,19 @@ export default function ManageInstitutionSection({
<div className="flex items-center gap-3 flex-1 min-w-0">
<Avatar className="h-10 w-10 flex-shrink-0 hidden sm:flex">
<AvatarImage
src={getProfessorProfilePicture(professor)}
alt={getProfessorName(professor)}
src={otherProfessorsInstance.profilePicture}
alt={otherProfessorsInstance.fullName}
/>
<AvatarFallback className="bg-gradient-to-br from-blue-400 to-green-400 text-white font-semibold">
{getProfessorInitials(professor)}
{otherProfessorsInstance.initials}
</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<p className="font-medium text-slate-800 truncate">
{getProfessorName(professor)}
{otherProfessorsInstance.fullName}
</p>
<p className="text-sm text-slate-600 truncate">
{getProfessorEmail(professor) ||
{otherProfessorsInstance.email ||
'Email no disponible'}
</p>
</div>
Expand All @@ -265,7 +265,7 @@ export default function ManageInstitutionSection({
onClick={() =>
handleRemoveProfessor(
professor.id,
getProfessorName(professor)
otherProfessorsInstance.fullName
)
}
disabled={isRemoving}
Expand All @@ -274,8 +274,8 @@ export default function ManageInstitutionSection({
</Button>
</div>
</div>
))
) : (
)}
)) : (
<div className="text-center py-8 border-2 border-dashed rounded-lg">
<Users className="w-12 h-12 text-slate-300 mx-auto mb-3" />
<p className="text-slate-500 text-sm">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState, useMemo } from 'react';
import Modal from '../../../ui/Modal/Modal';
import Button from '../../../ui/Button/Button';
import Input from '../../../ui/Input/Input';
import { Building2, Search, Users, AlertCircle, Send } from 'lucide-react';
import { Building2, Search, AlertCircle, Send } from 'lucide-react';
import type { Institution } from '../../../../types/entities';
import { useCreateJoinRequest } from '../../../../hooks/useJoinRequests';

Expand Down Expand Up @@ -80,10 +80,6 @@ export default function JoinInstitutionModal({
<div className="flex-1 min-w-0">
<h3 className="font-semibold text-slate-800 mb-1">{selectedInstitution.name}</h3>
<p className="text-sm text-slate-600 line-clamp-2">{selectedInstitution.description}</p>
<div className="flex items-center gap-2 mt-2">
<Users className="w-4 h-4 text-slate-400" />
<span className="text-sm text-slate-500">{selectedInstitution.professors?.length || 0} profesores</span>
</div>
</div>
</div>
</div>
Expand Down Expand Up @@ -134,19 +130,15 @@ export default function JoinInstitutionModal({
) : (
(filteredInstitutions || []).map((institution) => (
<div key={institution.institutionId} className="border border-slate-200 rounded-lg p-4 hover:border-blue-300 hover:bg-blue-50/50 transition-colors">
<div className="flex items-start justify-between gap-3">
<div className="flex items-center justify-between gap-3">
<div className="flex items-start gap-3 flex-1 min-w-0">
<div className="w-10 h-10 rounded-lg bg-purple-100 flex items-center justify-center flex-shrink-0">
<Building2 className="w-5 h-5 text-purple-600" />
</div>
<div className="flex-1 min-w-0">
<h4 className="font-semibold text-slate-800 mb-1">{institution.name}</h4>
<p className="text-sm text-slate-600 line-clamp-2 mb-2">{institution.description}</p>
<h4 className="font-semibold text-slate-800">{institution.name}</h4>
<p className="text-sm text-slate-600 line-clamp-2">{institution.description}</p>
<div className="flex items-center gap-4 text-xs text-slate-500">
<div className="flex items-center gap-1">
<Users className="w-3 h-3" />
<span>{institution.professors?.length || 0} profesores</span>
</div>
{institution.aliases && institution.aliases.length > 0 && (
<div className="flex items-center gap-1">
<span className="text-slate-400">•</span>
Expand Down
6 changes: 3 additions & 3 deletions src/components/ui/CardList/CardList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Card, CardContent, CardTitle, CardDescription } from '../Card/Card';
import { Link } from 'react-router-dom';
import type { Course } from '../../../types/entities';
import { formatCurrency } from '../../../lib/currency';
import { getProfessorName } from '../../../lib/professor';
import * as ProfessorModel from '../../../models/Professor';

interface CourseCardListProps extends React.HTMLAttributes<HTMLDivElement> {
/**
Expand All @@ -27,8 +27,8 @@ interface CourseCardListProps extends React.HTMLAttributes<HTMLDivElement> {
*/
const CardList = React.forwardRef<HTMLDivElement, CourseCardListProps>(
({ course, className, onViewMore, ...props }, ref) => {
const instructorName = getProfessorName(course.professor);

const professor = new ProfessorModel.Professor(course.professor);
const instructorName = professor.fullName;
const displayAmountStudents =
course?.studentsCount ?? course?.students?.length ?? 0;

Expand Down
7 changes: 7 additions & 0 deletions src/components/ui/PageLoader/PageLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const PageLoader = () => (
<div className="flex justify-center items-center h-screen">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
</div>
);

export default PageLoader;
3 changes: 0 additions & 3 deletions src/contexts/AuthProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
const login = useCallback(
async (token: string) => {
localStorage.setItem(TOKEN_STORAGE_KEY, token);
apiClient.defaults.headers.common['Authorization'] = `Bearer ${token}`;
await fetchProfileAndSetUser();
},
[fetchProfileAndSetUser]
Expand All @@ -46,7 +45,6 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {

['jwt_token', 'token', 'authToken'].forEach((k) => localStorage.removeItem(k));

delete apiClient.defaults.headers.common['Authorization'];
setUser(null);
setIsLoading(false);
}
Expand Down Expand Up @@ -76,7 +74,6 @@ export const AuthProvider = ({ children }: { children: ReactNode }) => {
};

if (token) {
apiClient.defaults.headers.common['Authorization'] = `Bearer ${token}`;
try {
await fetchProfileAndSetUser();
} catch {
Expand Down
13 changes: 7 additions & 6 deletions src/hooks/useProfessor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useQuery } from '@tanstack/react-query';
import apiClient from '../api/apiClient';
import type { Professor } from '../types/entities';
import type { ProfessorDTO } from '../types/entities';
import { Professor } from '../models/Professor';
import type { AxiosError } from 'axios';
import type { ApiResponse } from '../types/shared.ts';

Expand Down Expand Up @@ -29,9 +30,9 @@ export const useProfessorProfile = () => {
const response = await apiClient.get<{
status: number;
message: string;
data: Professor;
data: ProfessorDTO;
}>('/professors/me');
return response.data.data;
return new Professor(response.data.data);
},
// Only run this query if user is authenticated and is a professor
enabled: true,
Expand All @@ -48,10 +49,10 @@ export const useProfessors = () => {
queryKey: ['professors', 'all'],

queryFn: async () => {
const response = await apiClient.get<ApiResponse<Professor[]>>('/professors');
return response.data.data;
const response =
await apiClient.get<ApiResponse<ProfessorDTO[]>>('/professors');
return response.data.data.map((p) => new Professor(p));
},

});
};

Expand Down
75 changes: 0 additions & 75 deletions src/lib/professor.ts

This file was deleted.

Loading