Skip to content

Commit

Permalink
Added expo page at /expo (#61)
Browse files Browse the repository at this point in the history
* Added expo page

* Added page to view public project data
  • Loading branch information
MichaelZhao21 authored Nov 23, 2023
1 parent d7e478a commit 9b4e9a7
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 0 deletions.
5 changes: 5 additions & 0 deletions client/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Project from './pages/judge/project';

import './index.css';
import AdminSettings from './pages/admin/settings';
import Expo from './pages/Expo';

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);

Expand Down Expand Up @@ -51,6 +52,10 @@ const router = createBrowserRouter([
path: '/admin',
element: <Admin />,
},
{
path: '/expo',
element: <Expo />,
},
{
path: '/admin/add-projects',
element: <AddProjects />,
Expand Down
83 changes: 83 additions & 0 deletions client/src/pages/Expo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useEffect, useState } from 'react';
import Container from '../components/Container';
import { getRequest } from '../api';
import { errorAlert } from '../util';

const Expo = () => {
const [rawProjects, setRawProjects] = useState<PublicProject[]>([]);
const [projects, setProjects] = useState<PublicProject[]>([]);
const [nameSort, setNameSort] = useState(false);

// Fetch public project list from DB
useEffect(() => {
async function fetchProjects() {
const res = await getRequest<PublicProject[]>('/project/list/public', '');
if (res.status !== 200) {
errorAlert(res);
return;
}
setRawProjects(res.data as PublicProject[]);
}

fetchProjects();
}, []);

// On load or when sort changes, sort by name/table #
useEffect(() => {
if (!rawProjects) return;

const sortedProjects = [...rawProjects];
if (nameSort) {
sortedProjects.sort((a, b) => a.name.localeCompare(b.name));
} else {
sortedProjects.sort((a, b) => a.location - b.location);
}

setProjects(sortedProjects);
}, [rawProjects, nameSort]);

return (
<Container noCenter>
<h1 className="mt-4 text-4xl text-center font-bold">Project Expo</h1>
<h2 className="text-2xl text-center font-bold text-primary">
{process.env.REACT_APP_JURY_NAME}
</h2>
<table className="mb-4">
<thead>
<tr>
<th
onClick={() => setNameSort(true)}
className={
'px-4 py-2 cursor-pointer text-left ' + (nameSort && 'underline')
}
>
Name
</th>
<th
onClick={() => setNameSort(false)}
className={
'px-4 py-2 cursor-pointer text-left ' + (!nameSort && 'underline')
}
>
Table
</th>
</tr>
</thead>
<tbody>
{projects.map((project, idx) => (
<tr key={idx}>
<td className="px-4 py-2">
<a href={project.url} target="_blank" rel="noopener noreferrer">
{project.name}
</a>
</td>
<td className="px-4 py-2">{project.location}</td>
</tr>
))}
</tbody>
</table>
</Container>
);
};

export default Expo;
3 changes: 3 additions & 0 deletions client/src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ const App = () => {
<Button href="/judge/login" type="primary">
Judging Portal
</Button>
<Button href="/expo" type="outline" className="py-3 mt-4 mb-2">
Project Expo
</Button>
<Button href="/admin/login" type="text">
Admin Portal
</Button>
Expand Down
10 changes: 10 additions & 0 deletions client/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ interface Project {
last_activity: number;
}

interface PublicProject {
name: string;
location: number;
description: string;
url: string;
try_link: string;
video_link: string;
challenge_list: string;
}

interface Judge {
id: string;
name: string;
Expand Down
1 change: 1 addition & 0 deletions server/router/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func NewRouter(db *mongo.Database) *gin.Engine {
adminRouter.POST("/project/devpost", AddDevpostCsv)
adminRouter.POST("/project/new", AddProject)
adminRouter.GET("/project/list", ListProjects)
defaultRouter.GET("/project/list/public", ListPublicProjects)
adminRouter.POST("/project/csv", AddProjectsCsv)
judgeRouter.GET("/project/:id", GetProject)
judgeRouter.GET("/judge/vote/info", GetVotingProjectInfo)
Expand Down
39 changes: 39 additions & 0 deletions server/router/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,45 @@ func ListProjects(ctx *gin.Context) {
ctx.JSON(http.StatusOK, projects)
}

type PublicProject struct {
Name string `json:"name"`
Location int64 `json:"location"`
Description string `json:"description"`
Url string `json:"url"`
TryLink string `json:"tryLink"`
VideoLink string `json:"videoLink"`
ChallengeList string `json:"challengeList"`
}

func ListPublicProjects(ctx *gin.Context) {
// Get the database from the context
db := ctx.MustGet("db").(*mongo.Database)

// Get the projects from the database
projects, err := database.FindAllProjects(db)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "error getting projects from database: " + err.Error()})
return
}

// Convert projects to public projects
publicProjects := make([]PublicProject, len(projects))
for i, project := range projects {
publicProjects[i] = PublicProject{
Name: project.Name,
Location: project.Location,
Description: project.Description,
Url: project.Url,
TryLink: project.TryLink,
VideoLink: project.VideoLink,
ChallengeList: strings.Join(project.ChallengeList, ", "),
}
}

// Send OK
ctx.JSON(http.StatusOK, publicProjects)
}

// POST /project/csv - Endpoint to add projects from a CSV file
func AddProjectsCsv(ctx *gin.Context) {
// Get the database from the context
Expand Down

0 comments on commit 9b4e9a7

Please sign in to comment.