Skip to content
Merged
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
787 changes: 784 additions & 3 deletions frontend/spec-trackr-app/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions frontend/spec-trackr-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"bootstrap": "^5.3.6",
"gh-pages": "^6.3.0",
"lucide-react": "^0.513.0",
"next": "^15.3.3",
"react": "^19.1.0",
"react-bootstrap": "^2.10.10",
"react-dom": "^19.1.0",
Expand Down
26 changes: 0 additions & 26 deletions frontend/spec-trackr-app/src/App.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,3 @@
// import logo from './logo.svg';
// import './App.css';

// function App() {
// return (
// <div className="App">
// <header className="App-header">
// <img src={logo} className="App-logo" alt="logo" />
// <p>
// Edit <code>src/App.js</code> and save to reload.
// </p>
// <a
// className="App-link"
// href="https://reactjs.org"
// target="_blank"
// rel="noopener noreferrer"
// >
// Learn React
// </a>
// </header>
// </div>
// );
// }

// export default App;

import React, { useState } from "react";
import ComSp from "./com_sp"; // Desktop-1
import SpCom from "./sp_com"; // Desktop-2
Expand Down
20 changes: 19 additions & 1 deletion frontend/spec-trackr-app/src/com_sp.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useEffect } from "react";
import { FaArrowLeft } from "react-icons/fa";
import axios from "axios";
import {
Card,
Expand Down Expand Up @@ -31,7 +32,7 @@ const ComSp = ({ onSpecTabClick }) => {
const [companyOptions, setCompanyOptions] = useState([]);
const [positionOptions, setPositionOptions] = useState([]);
const [rawOptions, setRawOptions] = useState([]);
const [activeTab, setActiveTab] = useState("");
const [activeTab, setActiveTab] = useState("채용공고 검색");
const [jobPostingResults, setJobPostingResults] = useState([]);
const [companySearchTerm, setCompanySearchTerm] = useState(""); // 회사 검색어

Expand Down Expand Up @@ -133,6 +134,23 @@ const ComSp = ({ onSpecTabClick }) => {
// --- 렌더링 ---
return (
<Container className="mb-5">
<div style={{
position: "absolute",
top: 24,
left: 24,
display: "flex",
alignItems: "center",
zIndex: 10
}}>
<Button
variant="outline-dark"
style={{ display: "flex", alignItems: "center", gap: 6, fontWeight: 500 }}
onClick={() => { window.location.href = "http://localhost:3001"; }}
>
<FaArrowLeft style={{ fontSize: 18 }} />
메인으로
</Button>
</div>
{/* 상단 중앙 제목 */}
<div className="text-center my-5">
<h1 className="display-4 fw-bold mb-2" style={{ fontWeight: 700 }}>SpecTrackr</h1>
Expand Down
30 changes: 29 additions & 1 deletion frontend/spec-trackr-app/src/sp_com.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,23 @@ const SpCom = ({ onCompanyTabClick }) => {
// --- 렌더링 ---
return (
<Container className="mb-5">
<div style={{
position: "absolute",
top: 24,
left: 24,
display: "flex",
alignItems: "center",
zIndex: 10
}}>
<Button
variant="outline-dark"
style={{ display: "flex", alignItems: "center", gap: 6, fontWeight: 500 }}
onClick={() => { window.location.href = "http://localhost:3001"; }}
>
<FaArrowLeft style={{ fontSize: 18 }} />
메인으로
</Button>
</div>
{/* 상단 중앙 제목 */}
<div className="text-center my-5">
<h1 className="display-4 fw-bold mb-2" style={{ fontWeight: 700 }}>SpecTrackr</h1>
Expand All @@ -158,7 +175,7 @@ const SpCom = ({ onCompanyTabClick }) => {
{/* 버튼: 100% 가로, 반반, 검정/흰색 */}
<Row className="mb-4" style={{ marginLeft: 0, marginRight: 0 }}>
<Col xs={6} className="p-0">
<Button
{/* <Button
className="w-100 py-3 rounded-0 rounded-start"
variant={activeTab === "채용공고 검색" ? "dark" : "outline-dark"}
onClick={() => {
Expand All @@ -168,6 +185,17 @@ const SpCom = ({ onCompanyTabClick }) => {
style={{ fontSize: "1.2rem", fontWeight: 500, borderRight: 0 }}
>
채용공고 검색
</Button> */}
<Button
className="w-100 py-3 rounded-0 rounded-start"
variant={activeTab === "채용공고 검색" ? "dark" : "outline-dark"}
onClick={() => {
setActiveTab("채용공고 검색");
if (onCompanyTabClick) onCompanyTabClick();
}}
style={{ fontSize: "1.2rem", fontWeight: 500 }}
>
채용공고 검색
</Button>
</Col>
<Col xs={6} className="p-0">
Expand Down
27 changes: 27 additions & 0 deletions frontend/spectrackr-main/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules

# next.js
/.next/
/out/

# production
/build

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
3 changes: 3 additions & 0 deletions frontend/spectrackr-main/app/dashboard/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Loading() {
return null
}
83 changes: 83 additions & 0 deletions frontend/spectrackr-main/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"use client"

import { useState } from "react"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Button } from "@/components/ui/button"
import { ArrowLeft, Search, FileText } from "lucide-react"
import { useRouter } from "next/navigation"
import { ThemeProvider } from "@/components/theme-provider"
import { ThemeToggle } from "@/components/theme-toggle"

export default function Dashboard() {
return (
<ThemeProvider attribute="class" defaultTheme="dark" enableSystem disableTransitionOnChange>
<DashboardPage />
</ThemeProvider>
)
}

function DashboardPage() {
const router = useRouter()
const [activeTab, setActiveTab] = useState("job-search")

return (
<div className="min-h-screen bg-slate-100 dark:bg-slate-900 text-slate-900 dark:text-white">
<div className="container mx-auto px-4 py-8">
<div className="flex justify-between items-center mb-6">
<Button
variant="ghost"
onClick={() => router.push("/")}
className="text-slate-600 dark:text-slate-300 hover:text-slate-900 dark:hover:text-white"
>
<ArrowLeft className="mr-2 h-4 w-4" /> 메인으로 돌아가기
</Button>
<ThemeToggle />
</div>

<h1 className="text-3xl font-bold mb-8">SpecTrackr 대시보드</h1>

<Tabs defaultValue="job-search" value={activeTab} onValueChange={setActiveTab} className="w-full">
<TabsList className="grid w-full max-w-md grid-cols-2 mb-8">
<TabsTrigger value="job-search" className="text-lg py-3">
<Search className="mr-2 h-4 w-4" /> 채용공고 검색
</TabsTrigger>
<TabsTrigger value="spec-search" className="text-lg py-3">
<FileText className="mr-2 h-4 w-4" /> 스펙 검색
</TabsTrigger>
</TabsList>

<TabsContent
value="job-search"
className="p-6 bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700"
>
<h2 className="text-2xl font-bold mb-4">채용공고 검색</h2>
<p className="text-slate-600 dark:text-slate-300 mb-6">
다양한 취업 사이트의 채용공고를 한 곳에서 확인하고 비교할 수 있습니다. 원하는 직무나 회사를 검색해보세요.
</p>

{/* 여기에 채용공고 검색 기능 구현 */}
<div className="p-12 text-center text-slate-500 dark:text-slate-400 border border-dashed border-slate-300 dark:border-slate-600 rounded-lg">
채용공고 검색 기능이 여기에 구현됩니다.
</div>
</TabsContent>

<TabsContent
value="spec-search"
className="p-6 bg-white dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700"
>
<h2 className="text-2xl font-bold mb-4">스펙 검색</h2>
<p className="text-slate-600 dark:text-slate-300 mb-6">
실제 합격자 자소서와 스펙 사례를 기반으로 현실적인 준비 방법을 확인할 수 있습니다. 관심 있는 직무나 회사를
검색해보세요.
</p>

{/* 여기에 스펙 검색 기능 구현 */}
<div className="p-12 text-center text-slate-500 dark:text-slate-400 border border-dashed border-slate-300 dark:border-slate-600 rounded-lg">
스펙 검색 기능이 여기에 구현됩니다.
</div>
</TabsContent>
</Tabs>
</div>
</div>
)
}
142 changes: 142 additions & 0 deletions frontend/spectrackr-main/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;

--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;

--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;

--primary: 196 100% 50%;
--primary-foreground: 210 40% 98%;

--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;

--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;

--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;

--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 196 100% 50%;

--radius: 0.5rem;
}

.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;

--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;

--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;

--primary: 196 100% 50%;
--primary-foreground: 222.2 47.4% 11.2%;

--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;

--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;

--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;

--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;

--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 196 100% 50%;
}

.light {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;

--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;

--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;

--primary: 196 100% 50%;
--primary-foreground: 210 40% 98%;

--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;

--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;

--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;

--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;

--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 196 100% 50%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
}

::-webkit-scrollbar-track {
background: rgba(15, 23, 42, 0.3);
}

::-webkit-scrollbar-thumb {
background: rgba(148, 163, 184, 0.5);
border-radius: 4px;
}

::-webkit-scrollbar-thumb:hover {
background: rgba(148, 163, 184, 0.7);
}

/* Gradient animations */
@keyframes gradient-shift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}

.animate-gradient {
background-size: 200% 200%;
animation: gradient-shift 5s ease infinite;
}
Loading