Skip to content

Commit

Permalink
Merge pull request #12 from midas1214/main
Browse files Browse the repository at this point in the history
make rating page search same as download
  • Loading branch information
midas1214 authored Nov 10, 2024
2 parents f6fe5fc + 98d5b56 commit 6ae4e76
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 37 deletions.
38 changes: 20 additions & 18 deletions frontend/src/pages/download.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,37 +157,39 @@ const DownloadPage: React.FC = () => {

{error && <p style={{ color: 'red' }}>{error}</p>}

<div style={{ marginTop: '30px' }}>
<h3>Available Packages:</h3>
{packages.length > 0 ? (
{packages.length > 0 ? (
<div style={{ marginTop: '30px' }}>
<h3>Available Packages:</h3>
<ul style={{ listStyleType: 'none', padding: '0' }}>
{packages.map((pkg) => (
<li key={pkg.ID} style={{ marginBottom: '15px', padding: '10px', border: '1px solid #ddd', borderRadius: '8px', backgroundColor: '#f9f9f9' }}>
<strong>{pkg.Name}</strong> (v{pkg.Version})
<strong>{pkg.Name}</strong>
<button
onClick={() => handleDownload(pkg.ID)}
style={{ marginLeft: '15px', padding: '5px 10px', backgroundColor: '#28a745', color: '#fff', border: 'none', borderRadius: '4px', cursor: 'pointer' }}
>
Download
Get Rating
</button>
</li>
))}
</ul>
) : (
<p>No packages found. Try a different search term.</p>
)}

<div style={{ display: 'flex', justifyContent: 'center', marginTop: '20px' }}>
<button onClick={handlePreviousPage} disabled={offset === 0} style={{ padding: '8px 16px', marginRight: '10px', cursor: 'pointer' }}>
Previous Page
</button>
<button onClick={handleNextPage} style={{ padding: '8px 16px', cursor: 'pointer' }}>
Next Page
</button>

<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', marginTop: '20px' }}>
<button onClick={handlePreviousPage} disabled={offset === 0} style={{ padding: '8px 16px', marginRight: '10px', cursor: 'pointer' }}>
Previous Page
</button>
<span style={{ margin: '0 15px' }}>Current Page: {offset + 1}</span>
<button onClick={handleNextPage} style={{ padding: '8px 16px', cursor: 'pointer' }}>
Next Page
</button>
</div>
</div>
</div>
) : (
<p style={{ marginTop: '20px' }}>No packages found. Try a different search term.</p>
)}

</PageLayout>
);
};

export default DownloadPage;
export default DownloadPage;
187 changes: 168 additions & 19 deletions frontend/src/pages/rating.tsx
Original file line number Diff line number Diff line change
@@ -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<PackageMetadata[]>([]);
const [ratingData, setRatingData] = useState<RatingData | null>(null);
const [authToken, setAuthToken] = useState<string | null>(null);
const [error, setError] = useState<string | null>(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 (
<PageLayout title="Package Rating Overview">
<form onSubmit={handleSearch} style={{ maxWidth: '500px', margin: '0 auto' }}>
<form onSubmit={(e) => { e.preventDefault(); handleSearch(0); }} style={{ maxWidth: '500px', margin: '0 auto' }}>
<div style={{ marginBottom: '15px' }}>
<label>
Search for Package:
<input
type="text"
value={packageName}
onChange={(e) => setPackageName(e.target.value)}
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
required
style={{ width: '100%', padding: '8px', marginTop: '5px' }}
/>
</label>
</div>

<button type="submit" style={{ padding: '10px 20px', backgroundColor: '#007bff', color: '#fff', border: 'none', cursor: 'pointer' }}>
<button
type="submit"
style={{ padding: '10px 20px', backgroundColor: '#007bff', color: '#fff', border: 'none', cursor: 'pointer' }}
>
Search
</button>
</form>

{packageName && (
{error && <p style={{ color: 'red', marginTop: '20px' }}>{error}</p>}

{packages.length > 0 ? (
<div style={{ marginTop: '30px' }}>
<h3>Available Packages:</h3>
<ul style={{ listStyleType: 'none', padding: '0' }}>
{packages.map((pkg) => (
<li key={pkg.ID} style={{ marginBottom: '15px', padding: '10px', border: '1px solid #ddd', borderRadius: '8px', backgroundColor: '#f9f9f9' }}>
<strong>{pkg.Name}</strong>
<button
onClick={() => fetchRating(pkg.ID)}
style={{ marginLeft: '15px', padding: '5px 10px', backgroundColor: '#28a745', color: '#fff', border: 'none', borderRadius: '4px', cursor: 'pointer' }}
>
Get Rating
</button>
</li>
))}
</ul>

<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', marginTop: '20px' }}>
<button onClick={handlePreviousPage} disabled={offset === 0} style={{ padding: '8px 16px', marginRight: '10px', cursor: 'pointer' }}>
Previous Page
</button>
<span style={{ margin: '0 15px' }}>Current Page: {offset + 1}</span>
<button onClick={handleNextPage} style={{ padding: '8px 16px', cursor: 'pointer' }}>
Next Page
</button>
</div>
</div>
) : (
<p style={{ marginTop: '20px' }}>No packages found. Try a different search term.</p>
)}

{ratingData && (
<div style={{ marginTop: '30px', padding: '20px', border: '1px solid #ddd', borderRadius: '8px', backgroundColor: '#f9f9f9' }}>
<h3>Rating for: {packageName}</h3>
<h3>Rating Details</h3>
<p><strong>Overall Rating:</strong> {ratingData.overall} / 5</p>
<p><strong>Dependency Pinning:</strong> {ratingData.dependencyPinning.toFixed(2)}</p>
<p><strong>Code Review Metric:</strong> {ratingData.codeReviewMetric.toFixed(2)}</p>
Expand All @@ -48,4 +197,4 @@ const RatingPage: React.FC = () => {
);
};

export default RatingPage;
export default RatingPage;

0 comments on commit 6ae4e76

Please sign in to comment.