Skip to content

Commit 334cd4f

Browse files
authored
Fetch documents related to current org (#31)
1 parent 3bd06fb commit 334cd4f

5 files changed

Lines changed: 68 additions & 43 deletions

File tree

client/src/components/FileManager/ContentArea.tsx

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import React, { useEffect, useState } from "react";
22
import { X, FileText, Clock, Layers } from "lucide-react";
33
import { Button } from "../ui/button";
44
import { OrganizationProfile, useOrganization } from "@clerk/clerk-react";
5-
import { mockSlideDecks } from "../../models";
6-
import type { SlideDeck } from "../../models";
75
import { Link } from "@tanstack/react-router";
6+
import { useDocuments } from "../../hooks/useApi";
87

98
const ContentArea: React.FC = () => {
109
const { organization } = useOrganization();
1110
const [showOrgEditPanel, setShowOrgEditPanel] = useState(false);
12-
const [slideDecks, setSlideDecks] = useState<SlideDeck[]>([]);
11+
12+
// Fetch documents for the current organization
13+
const { data: documents, isLoading: documentsLoading, error: documentsError } = useDocuments(organization?.id);
1314

1415
useEffect(() => {
1516
const handleToggleOrgEdit = () => {
@@ -23,22 +24,6 @@ const ContentArea: React.FC = () => {
2324
};
2425
}, []);
2526

26-
useEffect(() => {
27-
if (organization?.id) {
28-
// In a real app, we would fetch slides from an API using the organization ID
29-
30-
// This is the filtering logic that would be used in a real app
31-
// const orgSlides = mockSlideDecks.filter(deck => deck.organizationId === organization.id);
32-
33-
// For now, show all slides for every organization
34-
const orgSlides = mockSlideDecks;
35-
36-
setSlideDecks(orgSlides);
37-
} else {
38-
setSlideDecks([]);
39-
}
40-
}, [organization?.id]);
41-
4227
// Format date to relative time (e.g., "2 days ago")
4328
const formatRelativeTime = (dateString: string): string => {
4429
const date = new Date(dateString);
@@ -73,35 +58,53 @@ const ContentArea: React.FC = () => {
7358
<div className="h-full">
7459
<h2 className="text-xl font-semibold mb-6">{organization.name} Materials</h2>
7560

76-
{slideDecks.length > 0 ? (
61+
{documentsLoading ? (
7762
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
78-
{slideDecks.map((deck) => (
63+
{[...Array(3)].map((_, i) => (
64+
<div key={i} className="bg-white rounded-lg shadow animate-pulse">
65+
<div className="p-4">
66+
<div className="h-4 bg-gray-200 rounded mb-2"></div>
67+
<div className="h-3 bg-gray-200 rounded w-2/3"></div>
68+
</div>
69+
</div>
70+
))}
71+
</div>
72+
) : documentsError ? (
73+
<div className="flex flex-col items-center justify-center h-64 bg-white rounded-lg p-8 text-center">
74+
<FileText className="h-16 w-16 text-red-300 mb-4" />
75+
<h3 className="text-lg font-medium text-gray-800 mb-2">Error loading documents</h3>
76+
<p className="text-gray-500">Please try again later</p>
77+
</div>
78+
) : documents && documents.length > 0 ? (
79+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
80+
{documents.map((doc) => (
7981
<div
80-
key={deck.id}
82+
key={doc.id}
8183
className="bg-white rounded-lg shadow hover:shadow-md transition-shadow overflow-hidden flex flex-col cursor-pointer"
8284
>
8385
<div className="p-4 flex-1 flex flex-col">
8486
<div className="flex items-center mb-3">
8587
<FileText className="h-5 w-5 text-blue-500 mr-2" />
86-
<h3 className="font-medium text-lg text-gray-800">{deck.title}</h3>
88+
<h3 className="font-medium text-lg text-gray-800">{doc.name}</h3>
8789
</div>
88-
<div className="mt-2 flex items-center text-sm text-gray-500 space-x-4">
90+
{doc.description && (
91+
<p className="text-sm text-gray-600 mb-2">{doc.description}</p>
92+
)}
93+
<div className="mt-auto flex items-center text-sm text-gray-500 space-x-4">
8994
<div className="flex items-center">
9095
<Clock className="h-4 w-4 mr-1" />
91-
<span>{formatRelativeTime(deck.uploadedAt)}</span>
96+
<span>{formatRelativeTime(doc.createdAt)}</span>
97+
</div>
98+
<div className="flex items-center">
99+
<Layers className="h-4 w-4 mr-1" />
100+
<span>{doc.chunkCount} chunks</span>
92101
</div>
93-
{deck.slideCount && (
94-
<div className="flex items-center">
95-
<Layers className="h-4 w-4 mr-1" />
96-
<span>{deck.slideCount} slides</span>
97-
</div>
98-
)}
99102
</div>
100103
</div>
101104
<div className="px-4 py-3 bg-gray-50 border-t border-gray-100">
102-
<Link to="/slide/$slideId" params={{ slideId: deck.id }}>
105+
<Link to="/slide/$slideId" params={{ slideId: doc.id.toString() }}>
103106
<Button variant="ghost" size="sm" className="text-blue-600 w-full">
104-
View
107+
View Document
105108
</Button>
106109
</Link>
107110
</div>
@@ -111,7 +114,7 @@ const ContentArea: React.FC = () => {
111114
) : (
112115
<div className="flex flex-col items-center justify-center h-64 bg-white rounded-lg p-8 text-center">
113116
<FileText className="h-16 w-16 text-gray-300 mb-4" />
114-
<h3 className="text-lg font-medium text-gray-800 mb-2">No slide decks yet</h3>
117+
<h3 className="text-lg font-medium text-gray-800 mb-2">No documents yet</h3>
115118
<p className="text-gray-500">Upload materials to get started</p>
116119
</div>
117120
)}

client/src/hooks/useApi.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,11 @@ const api = {
6666
},
6767

6868
// Document service endpoints
69-
getDocuments: async (): Promise<Document[]> => {
70-
const response = await fetch(`${API_BASE}/api/documents`);
69+
getDocuments: async (organizationId?: string): Promise<Document[]> => {
70+
const url = organizationId
71+
? `${API_BASE}/api/documents?organizationId=${encodeURIComponent(organizationId)}`
72+
: `${API_BASE}/api/documents`;
73+
const response = await fetch(url);
7174
if (!response.ok) throw new Error('Failed to fetch documents');
7275
return response.json();
7376
},
@@ -173,10 +176,10 @@ export function useServiceApiDocs(serviceName: string) {
173176
}
174177

175178
// Document hooks
176-
export function useDocuments() {
179+
export function useDocuments(organizationId?: string) {
177180
return useQuery({
178-
queryKey: ['documents'],
179-
queryFn: api.getDocuments,
181+
queryKey: ['documents', organizationId],
182+
queryFn: () => api.getDocuments(organizationId),
180183
staleTime: 30000, // 30 seconds
181184
});
182185
}

server/document-service/src/main/java/de/tum/team_sigma/document_service/controller/DocumentController.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,27 @@ public ResponseEntity<DocumentResponse> uploadDocument(
7979
}
8080

8181
@GetMapping
82-
@Operation(summary = "Get all documents", description = "Retrieve a list of all documents")
82+
@Operation(summary = "Get all documents", description = "Retrieve a list of all documents, optionally filtered by organization")
8383
@ApiResponses(value = {
8484
@ApiResponse(responseCode = "200", description = "Documents retrieved successfully",
8585
content = @Content(schema = @Schema(implementation = DocumentResponse.class))),
8686
@ApiResponse(responseCode = "500", description = "Internal server error")
8787
})
88-
public ResponseEntity<List<DocumentResponse>> getAllDocuments() {
88+
public ResponseEntity<List<DocumentResponse>> getAllDocuments(
89+
@Parameter(description = "Organization ID to filter documents")
90+
@RequestParam(value = "organizationId", required = false) String organizationId) {
8991
try {
90-
List<DocumentResponse> documents = documentService.getAllDocuments();
92+
List<DocumentResponse> documents;
93+
if (organizationId != null && !organizationId.trim().isEmpty()) {
94+
documents = documentService.getDocumentsByOrganization(organizationId);
95+
logger.info("Retrieved {} documents for organization: {}", documents.size(), organizationId);
96+
} else {
97+
documents = documentService.getAllDocuments();
98+
logger.info("Retrieved {} documents (no organization filter)", documents.size());
99+
}
91100
return ResponseEntity.ok(documents);
92101
} catch (Exception e) {
93-
logger.error("Failed to get all documents", e);
102+
logger.error("Failed to get documents", e);
94103
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
95104
}
96105
}

server/document-service/src/main/java/de/tum/team_sigma/document_service/repository/DocumentRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public interface DocumentRepository extends JpaRepository<Document, Long> {
1818

1919
List<Document> findByContentType(String contentType);
2020

21+
List<Document> findByOrganizationId(String organizationId);
22+
2123
@Query("SELECT d FROM Document d LEFT JOIN FETCH d.chunks WHERE d.id = :id")
2224
Optional<Document> findByIdWithChunks(@Param("id") Long id);
2325

server/document-service/src/main/java/de/tum/team_sigma/document_service/service/DocumentService.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,14 @@ public List<DocumentResponse> getAllDocuments() {
178178
.collect(Collectors.toList());
179179
}
180180

181+
@Transactional(readOnly = true)
182+
public List<DocumentResponse> getDocumentsByOrganization(String organizationId) {
183+
logger.info("Fetching documents for organization: {}", organizationId);
184+
return documentRepository.findByOrganizationId(organizationId).stream()
185+
.map(DocumentResponse::new)
186+
.collect(Collectors.toList());
187+
}
188+
181189
@Transactional(readOnly = true)
182190
public DocumentResponse getDocumentById(Long id) {
183191
Document document = documentRepository.findByIdWithChunks(id)

0 commit comments

Comments
 (0)