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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
.DS_Store
*.log
.env
*.pem
.idea/

.idea/
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# PiroCheck
# 🏫 PiroCheck
피로그래밍 과제/출석/보증금 관리 서비스
3 changes: 2 additions & 1 deletion frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ dist-ssr
*.sw?


.env
*.env
*.pem
10 changes: 10 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"lucide-react": "^0.507.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router-dom": "^7.5.3"
Expand Down
1 change: 0 additions & 1 deletion frontend/public/vite.svg

This file was deleted.

53 changes: 22 additions & 31 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,26 @@
import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'

import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Login from "./Login";
import Home from "./Home";
import Assignment from "./Assignment";
import Deposit from "./Deposit";
import Intro from "./Intro";
import Admin from "./Admin";
import Attendance from "./Attendance";
function App() {
const [count, setCount] = useState(0)

return (
<>
<div>
<a href="https://vite.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.jsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
)
<BrowserRouter>
<Routes>
<Route path="/" element={<Intro />} />
<Route path="/login" element={<Login />} />
<Route path="/home" element={<Home />} />
<Route path="/assignment" element={<Assignment />} />
<Route path="/attendance" element={<Attendance />} />
<Route path="/deposit" element={<Deposit />} />
<Route path="/admin" element={<Admin />} />
</Routes>
</BrowserRouter>
);
}

export default App
export default App;
Binary file added frontend/src/assets/img/arrowicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions frontend/src/assets/img/arrowicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/img/moneyicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions frontend/src/assets/img/moneyicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion frontend/src/assets/react.svg

This file was deleted.

33 changes: 33 additions & 0 deletions frontend/src/assets/root.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@font-face {
font-family: "Cafe24Moyamoya-Regular-v1.0";
src: url("https://fastly.jsdelivr.net/gh/projectnoonnu/[email protected]/Cafe24Moyamoya-Regular-v1.0.woff2")
format("woff2");
font-weight: normal;
font-style: normal;
}


:root {
--main-green: #49ff24;
--card-toggle-green: #2aff00;
--card-detail-green: #2d791d;
--icon-top-green: #14ae5c;
--icon-detail-green: #14ae5c;
--icon-detail-yellow: #ffcd29;
--icon-detail-red: #ff2c2c;
--background-black: #000000;
--fill-gray: #d9d9d9;
--warn-red: #ff5858;
--text-white: #ffffff;
--border-gray: #c7c7c7;
}
.noto-sans-kr-context {
font-family: "Noto Sans KR", sans-serif;
font-optical-sizing: auto;
font-weight: 400;
font-style: normal;
}

.inter{
font-family: "Inter", sans-serif;
}
42 changes: 42 additions & 0 deletions frontend/src/components/DailyOpenBlock.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { useState } from "react";
import "./componentsCss/DailyOpenBlock.css";

const DailyOpenBlock = ({ day, subject, tasks }) => {
const [open, setOpen] = useState(false);

const toggleOpen = () => {
setOpen(!open);
};

return (
<div className="daily-open-block">
<button
className={`daily-button ${open ? "active" : ""}`}
onClick={toggleOpen}
>
<div className="daily-open-header">
<span className="day">{day}</span>
<span className="subject">{subject}</span>
</div>
<span className={`arrow ${open ? "rotate" : ""}`}>▾</span>
</button>

{open && (
<div className="task-list">
{tasks.map((task, index) => (
<div className={`task-item ${task.status}`} key={index}>
<span>{task.label}</span>
<span className="task-icon">
{task.status === "done" && "◯"}
{task.status === "progress" && "△"}
{task.status === "fail" && "✕"}
</span>
</div>
))}
</div>
)}
</div>
);
};

export default DailyOpenBlock;
35 changes: 35 additions & 0 deletions frontend/src/components/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { ArrowLeft, Wallet } from 'lucide-react';
import './componentsCss/Header.css';
import arrowIcon from '../assets/img/arrowicon.svg';
import moneyIcon from '../assets/img/moneyicon.svg';
const Header = () => {
const navigate = useNavigate();
const location = useLocation();
const path = location.pathname;

let title = "ATTENDANCE\nCHECK";
if (path.includes('assignment')) title = "ASSIGNMENT\nCHECK";
else if (path.includes('deposit')) title = "DEPOSIT";

const showRightButton = !path.includes('deposit');

return (
<header className="header-container">
<button className="icon-button" onClick={() => navigate(-1)} aria-label="뒤로가기">
<img src={arrowIcon} alt="Back" width={34} height={34} />
</button>
<h1 className="header-title">{title}</h1>
{showRightButton ? (
<button className="icon-button" onClick={() => navigate('/deposit')} aria-label="보증금 페이지 이동">
<img src={moneyIcon} alt="Deposit" width={30} height={30} />
</button>
) : (
<div style={{ width: '30px' }} /> // 오른쪽 공백 유지
)}
</header>
);
};

export default Header;
12 changes: 12 additions & 0 deletions frontend/src/components/InfoBlock.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";

const InfoBlock = () => {
return (
<div>
<p className={InfoBlock.title}></p>
<p className={InfoBlock.context}></p>
</div>
);
};

export default InfoBlock;
18 changes: 18 additions & 0 deletions frontend/src/components/InputBlock.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from "react";
import "./componentsCss/InfoBlock.css";

const InputBlock = () => {
return (
<div>
<input class="inputTag" type="text" placeholder="이름" />
<input class="inputTag" type="password" placeholder="비밀번호" />
<input
class="inputTag"
type="text"
placeholder="출석코드를 입력하세요."
/>
</div>
);
};

export default InputBlock;
15 changes: 15 additions & 0 deletions frontend/src/components/PageBtn.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from "react";

const PageBtn = ({ buttons }) => {
return (
<div>
{buttons.map((btn, index) => (
<button key={index} onClick={() => (window.location.href = btn.href)}>
{btn.label}
</button>
))}
</div>
);
};

export default PageBtn;
44 changes: 44 additions & 0 deletions frontend/src/components/WeeklyListBlock.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { useState } from "react";
import "./componentsCss/WeeklyListBlock.css";
import DailyOpenBlock from "./DailyOpenBlock";

const WeeklyListBlock = ({ weeks }) => {
const [openIndex, setOpenIndex] = useState(null);

const toggleOpen = (index) => {
setOpenIndex(index === openIndex ? null : index);
};

return (
<div className="weekly-list">
{weeks.map((week, index) => (
<div key={index} className="weekly-item">
<button
className={`weekly-button ${openIndex === index ? "active" : ""}`}
onClick={() => toggleOpen(index)}
>
<span>{week.label}</span>
<span className={`arrow ${openIndex === index ? "rotate" : ""}`}>
</span>
</button>
{openIndex === index && (

<div className="week-details">
{week.details?.map((detail, i) => (
<DailyOpenBlock
key={i}
day={detail.day}
subject={detail.subject}
tasks={detail.tasks}
/>
))}
</div>
)}
</div>
))}
</div>
);
};

export default WeeklyListBlock;
41 changes: 41 additions & 0 deletions frontend/src/components/WeeklyOpenBlock.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React, { useState } from "react";
import "./componentsCss/DailyOpenBlock.css";
import "./componentsCss/WeeklyListBlock.css";
import DailyOpenBlock from "./DailyOpenBlock";

const WeeklyOpenBlock = ({ label, days }) => {
const [isOpen, setIsOpen] = useState(false);

const toggleOpen = () => {
setIsOpen(!isOpen);
};

return (
<div className={`weekly-wrapper ${isOpen ? "active" : ""}`}>
<div className="weekly-header">
<button className="weekly-button" onClick={toggleOpen}>
<span className="weekly-label">{label}</span>
<span className={`arrow ${isOpen ? "rotate" : ""}`}>▾</span>
</button>
{isOpen && (
<button className="close-button" onClick={toggleOpen}>✕</button>
)}
</div>

{isOpen && (
<div className="daily-open-block">
{days.map((dayData, index) => (
<DailyOpenBlock
key={index}
day={dayData.day}
subject={dayData.subject}
tasks={dayData.tasks}
/>
))}
</div>
)}
</div>
);
};

export default WeeklyOpenBlock;
Loading
Loading