Skip to content
Open
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
2 changes: 2 additions & 0 deletions backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
Expand Down
1 change: 0 additions & 1 deletion backend/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"fmt"
"log"
"net/http"
"os"
"log"
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
SignUpButton,
UserButton,
} from '@clerk/clerk-react'
import WebSocketTestClient from './WebSocketTestClient.tsx'
import WebSocketTestClient from './components/WebSocketTestClient.tsx'
import InterviewList from './components/InterviewList.tsx'

export default function App() {
return (
Expand All @@ -17,6 +18,7 @@ export default function App() {
</SignedOut>
<SignedIn>
<UserButton />
<InterviewList />
</SignedIn>
</header>
<main>
Expand Down
19 changes: 19 additions & 0 deletions frontend/src/components/InterviewList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useInterviews, type Interview } from '../hooks/useInterviews.ts';
import InterviewTile from './InterviewTile.tsx';

function InterviewList() {
const { interviews, loading, error } = useInterviews();

return (
<div>
<h1>Interview List</h1>
{loading && <p>Loading...</p>}
{error && <p>Error: {error}</p>}
{interviews.map((interview: Interview) => (
<InterviewTile key={interview.title} interview={interview} />
))}
</div>
)
}

export default InterviewList;
87 changes: 87 additions & 0 deletions frontend/src/components/InterviewTile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { type Interview } from '../hooks/useInterviews.ts';

interface InterviewTileProps {
interview: Interview;
}

function InterviewTile({ interview }: InterviewTileProps) {
return (
<div style={{
backgroundColor: '#ffffff',
borderRadius: '8px',
padding: '16px',
marginBottom: '12px',
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.1)',
position: 'relative',
display: 'flex',
flexDirection: 'column',
gap: '8px'
}}>
{/* Title, date, and collapse icon */}
<div style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'flex-start'
}}>
<div style={{ flex: 1 }}>
<h2 style={{
margin: 0,
fontSize: '16px',
fontWeight: 600,
color: '#333333',
marginBottom: '4px'
}}>
{interview.title}
</h2>
</div>
{/* Collapse icon */}
<div style={{
color: '#888888',
cursor: 'pointer',
fontSize: '14px'
}}>
</div>
</div>

{/* Bottom section with candidate info */}
<div style={{
display: 'flex',
alignItems: 'center',
marginTop: '8px'
}}>
{/* Candidate info */}
<div style={{
display: 'flex',
alignItems: 'center',
gap: '8px'
}}>
<div style={{
width: '32px',
height: '32px',
borderRadius: '50%',
backgroundColor: '#9333ea',
color: '#ffffff',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '14px',
fontWeight: 600
}}>
{interview.candidate.charAt(0).toUpperCase()}
</div>
<span style={{
color: '#2563eb',
fontSize: '14px',
fontWeight: 500,
cursor: 'pointer'
}}>
{interview.candidate}
</span>
</div>
</div>
</div>
);
}

export default InterviewTile;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from 'react';
import './App.css';
import '../App.css';

type MessageType = 'system' | 'received' | 'sent' | 'error';

Expand Down
56 changes: 56 additions & 0 deletions frontend/src/hooks/useInterviews.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useState, useEffect } from 'react';

export interface Interview {
id: string;
title: string;
content: string;
interviewer: string;
candidate: string;
}

export function useInterviews() {
const [interviews, setInterviews] = useState<Interview[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);

useEffect(() => {
let cancelled = false;

const fetchInterviews = async () => {
try {
setLoading(true);
setError(null);

// TODO: Replace with actual API call after MongoDB is set up
const mockInterviews = await new Promise<Interview[]>((resolve) => {
setTimeout(() => {
resolve([
{ id: '1', title: 'Mock w/ Shimmy', content: '// foo', interviewer: 'Jason', candidate: 'Shimmy' },
{ id: '2', title: 'Mock w/ Freaknd', content: '// bar', interviewer: 'Jason', candidate: 'Freaknd' },
{ id: '3', title: 'Mock2 w/ Shimmy', content: '// baz', interviewer: 'Jason', candidate: 'Shimmy' },
]);
}, 500);
});

if (!cancelled) {
setInterviews(mockInterviews);
setLoading(false);
}
} catch (err) {
if (!cancelled) {
setError(err instanceof Error ? err.message : 'Unknown error');
setLoading(false);
}
}
};

fetchInterviews();

return () => {
cancelled = true;
};
}, []);

return { interviews, loading, error };
}