diff --git a/frontend/src/pages/download.tsx b/frontend/src/pages/download.tsx
index 1991a35..7ad3b06 100644
--- a/frontend/src/pages/download.tsx
+++ b/frontend/src/pages/download.tsx
@@ -157,37 +157,39 @@ const DownloadPage: React.FC = () => {
{error &&
-
Available Packages:
- {packages.length > 0 ? (
+ {packages.length > 0 ? (
+
+
Available Packages:
{packages.map((pkg) => (
-
- {pkg.Name} (v{pkg.Version})
+ {pkg.Name}
))}
- ) : (
-
No packages found. Try a different search term.
- )}
-
-
-
-
+
+
+
+ Current Page: {offset + 1}
+
+
-
+ ) : (
+
No packages found. Try a different search term.
+ )}
+
);
};
-export default DownloadPage;
+export default DownloadPage;
\ No newline at end of file
diff --git a/frontend/src/pages/rating.tsx b/frontend/src/pages/rating.tsx
index 8efdfb5..b8820e9 100644
--- a/frontend/src/pages/rating.tsx
+++ b/frontend/src/pages/rating.tsx
@@ -1,44 +1,193 @@
-import React, { useState } from 'react';
+import React, { useState, useEffect } from 'react';
import PageLayout from './pageLayout';
+interface PackageMetadata {
+ ID: string;
+ Name: string;
+ Version: string;
+}
+
+interface RatingData {
+ overall: number;
+ dependencyPinning: number;
+ codeReviewMetric: number;
+}
+
const RatingPage: React.FC = () => {
- const [packageName, setPackageName] = useState('');
- const [ratingData, setRatingData] = useState({
- overall: 4,
- dependencyPinning: 0.8,
- codeReviewMetric: 0.75,
- });
-
- const handleSearch = (e: React.FormEvent) => {
- e.preventDefault();
- console.log('Searching for:', packageName);
- // Add logic to fetch rating details for the entered package name
+ const [searchTerm, setSearchTerm] = useState('');
+ const [packages, setPackages] = useState
([]);
+ const [ratingData, setRatingData] = useState(null);
+ const [authToken, setAuthToken] = useState(null);
+ const [error, setError] = useState(null);
+ const [offset, setOffset] = useState(0);
+
+ // Retrieve auth token from localStorage on component mount
+ useEffect(() => {
+ const token = localStorage.getItem('authToken');
+ if (token) {
+ setAuthToken(token);
+ } else {
+ alert('Authentication token not found. Please log in.');
+ }
+ }, []);
+
+ // Fetch packages based on search term and offset (pagination)
+ const handleSearch = async (page = 0) => {
+ setError(null);
+ setPackages([]);
+ setRatingData(null); // Reset rating data on new search
+
+ if (!authToken) {
+ alert('Authentication token is missing. Please log in.');
+ return;
+ }
+
+ try {
+ const requestBody = [{ Name: searchTerm }];
+
+ const response = await fetch(`/packages?offset=${page}`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Authorization': authToken,
+ },
+ body: JSON.stringify(requestBody),
+ });
+
+
+ // Simulate response data
+ // const response1 = JSON.stringify({
+ // status: 200,
+ // data: [
+ // {
+ // Name: 'example-package',
+ // Version: '1.0.0',
+ // ID: '1',
+ // },
+ // {
+ // Name: 'another-package',
+ // Version: '2.0.1',
+ // ID: '2',
+ // },
+ // ],
+ // headers: {
+ // offset: '10',
+ // },
+ // });
+ // const response = JSON.parse(response1);
+
+ if (response.status === 200) {
+ const data: PackageMetadata[] = await response.json();
+ setPackages(data);
+ setOffset(page); // Update offset with the current page number
+ } else if (response.status === 400) {
+ setError('Search failed: Missing fields or invalid query.');
+ } else if (response.status === 403) {
+ setError('Search failed: Authentication failed due to invalid or missing AuthenticationToken.');
+ } else if (response.status === 413) {
+ setError('Search failed: Too many packages returned.');
+ } else {
+ setError('Search failed with an unknown error.');
+ }
+ } catch (err) {
+ console.error('Error during search:', err);
+ setError('An error occurred while searching for packages.');
+ }
+ };
+
+ // Fetch rating for a specific package
+ const fetchRating = async (packageId: string) => {
+ setError(null);
+ setRatingData(null);
+
+ try {
+ const response = await fetch(`/ratings?packageId=${encodeURIComponent(packageId)}`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+
+ if (response.ok) {
+ const data: RatingData = await response.json();
+ setRatingData(data);
+ } else {
+ setError('Failed to fetch rating. Please try again.');
+ }
+ } catch (err) {
+ console.error('Error fetching rating:', err);
+ setError('An error occurred while fetching the rating.');
+ }
+ };
+
+ const handleNextPage = () => {
+ handleSearch(offset + 1); // Move to the next page
+ };
+
+ const handlePreviousPage = () => {
+ if (offset > 0) handleSearch(offset - 1); // Move to the previous page if possible
};
return (
-
- {packageName && (
+ {error && {error}
}
+
+ {packages.length > 0 ? (
+
+
Available Packages:
+
+ {packages.map((pkg) => (
+ -
+ {pkg.Name}
+
+
+ ))}
+
+
+
+
+ Current Page: {offset + 1}
+
+
+
+ ) : (
+ No packages found. Try a different search term.
+ )}
+
+ {ratingData && (
-
Rating for: {packageName}
+
Rating Details
Overall Rating: {ratingData.overall} / 5
Dependency Pinning: {ratingData.dependencyPinning.toFixed(2)}
Code Review Metric: {ratingData.codeReviewMetric.toFixed(2)}
@@ -48,4 +197,4 @@ const RatingPage: React.FC = () => {
);
};
-export default RatingPage;
+export default RatingPage;
\ No newline at end of file