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
25 changes: 25 additions & 0 deletions reactStudy1week/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
*.Zone.Identifier
2 changes: 2 additions & 0 deletions reactStudy1week/.gitignore:Zone.Identifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3
12 changes: 12 additions & 0 deletions reactStudy1week/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# React + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## Expanding the ESLint configuration

If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
2 changes: 2 additions & 0 deletions reactStudy1week/README.md:Zone.Identifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3
33 changes: 33 additions & 0 deletions reactStudy1week/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'

export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...reactHooks.configs.recommended.rules,
'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
2 changes: 2 additions & 0 deletions reactStudy1week/eslint.config.js:Zone.Identifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3
13 changes: 13 additions & 0 deletions reactStudy1week/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
2 changes: 2 additions & 0 deletions reactStudy1week/index.html:Zone.Identifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3
33 changes: 33 additions & 0 deletions reactStudy1week/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "react-study-first-week",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"@tailwindcss/postcss": "^4.1.4",
"@tailwindcss/vite": "^4.1.4",
"autoprefixer": "^10.4.21",
"postcss": "^8.5.3",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwindcss": "^4.1.4"
},
"devDependencies": {
"@eslint/js": "^9.22.0",
"@types/react": "^19.0.10",
"@types/react-dom": "^19.0.4",
"@vitejs/plugin-react": "^4.3.4",
"eslint": "^9.22.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.19",
"globals": "^16.0.0",
"vite": "^6.3.1"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
2 changes: 2 additions & 0 deletions reactStudy1week/package.json:Zone.Identifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3
1 change: 1 addition & 0 deletions reactStudy1week/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions reactStudy1week/public/vite.svg:Zone.Identifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3
48 changes: 48 additions & 0 deletions reactStudy1week/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

@import 'tailwindcss';
/* @import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities'; */

/* #root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}

.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}

@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}

.card {
padding: 2em;
}

.read-the-docs {
color: #888;
} */
2 changes: 2 additions & 0 deletions reactStudy1week/src/App.css:Zone.Identifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3
36 changes: 36 additions & 0 deletions reactStudy1week/src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useState } from 'react'
import './App.css'
import Card from './components/Card'

function App() {
const [count, setCount] = useState(0)
const memberInfoList = [
{
id: 1,
name: "박상길",
department: "인사팀",
joinDate: "2022-04-19"
},
{
id: 2,
name: "정진호",
department: "기획팀",
joinDate: "2012-02-20"
},
{
id:3,
name: "연민수",
department: "해외영업팀",
joinDate: "2010-01-11"
}
]
return (
<div>
{memberInfoList.map(memberInfo => {
return <Card memberInfo={memberInfo} key={memberInfo.id}></Card>
})}
</div>
)
}

export default App
2 changes: 2 additions & 0 deletions reactStudy1week/src/App.jsx:Zone.Identifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3
1 change: 1 addition & 0 deletions reactStudy1week/src/assets/react.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions reactStudy1week/src/assets/react.svg:Zone.Identifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3
96 changes: 96 additions & 0 deletions reactStudy1week/src/components/Card.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useState } from "react";

function Card(props) {
const [isWorking, setIsWorking] = useState(false)
const [isLate, setIsLate] = useState(false)
const memberInfo = props.memberInfo;
const nowDate = new Date();
const joinDate = new Date(memberInfo.joinDate);
const diffTime = nowDate.getTime() - joinDate.getTime();
const diffDays = diffTime / (1000 * 60 * 60 * 24)
const diffYears = Math.floor(diffDays / 365)
memberInfo.diffYears = diffYears;
if (memberInfo.department === "인사팀") {
memberInfo.backgroundColor = "bg-lime-200"
}
if (memberInfo.department === "기획팀") {
memberInfo.backgroundColor = "bg-sky-200"
}
if (memberInfo.department === "해외영업팀") {
memberInfo.backgroundColor = "bg-red-200"
}
// 출퇴근 상태 변경
function changeWorkingState(id) {
// isWorking == false -> 퇴근 상태
// isWorking == true -> 출근 상태
const currentHour = new Date();
setIsWorking(!isWorking);
localStorage.setItem(id, currentHour)

// 9시 이후 출근 시 지각 표시
if (!isWorking && currentHour.getHours() >= 9 && currentHour.getMinutes() >= 0) {
setIsLate(true);
}

if (isWorking) {
setIsLate(false)
}
}
// 출퇴근 시간 localStorage 저장
function getCheckedHour(id) {
return localStorage.getItem(id)
}
// Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
// state를 변화시키는 함수가 무한루프에 빠지게 되면 발생하는 에러로 볼 수 있음
// state를 변화시키는 함수가 사용자 액션 시에만 동작하도록 해야함 -> 특히 이벤트 트리거에 연관된 함수
return (
<div className="max-w-sm w-full lg:max-w-full lg:flex pb-3">
<div className="h-48 lg:h-auto w-128 lg:w-128 flex-none bg-cover rounded-t lg:rounded-t-none lg:rounded-l text-center overflow-hidden">
</div>
<div className={memberInfo.backgroundColor + " lg:w-128 w-128 border-r border-b lg:border-l border-gray-400 lg:border-t lg:border-gray-400 rounded-xl lg:rounded-xl p-4 flex flex-col justify-between leading-normal"}>
<div className="mb-8">
{
Object.keys(memberInfo).map(key => {
let fieldName = ""
if (key === "name") {
fieldName = "이름"
}
if (key === "department") {
fieldName = "부서"
}
if (key === "joinDate") {
fieldName = "입사일"
}
if (key === "diffYears") {
fieldName = "년차"
}
return (
<div key={key + memberInfo.name}>
{
fieldName === '' ? <></> :
<p className="text-base text-black-600 flex items-center" >
{fieldName}: {memberInfo[key]}
</p>
}
</div>
)
})
}
<div>
<p className="text-base text-black-600 flex items-center">
{isWorking ? '출근 완료' : '퇴근 완료'} {isLate ? '지각입니다' : ''}
</p>
<p className="text-base text-black-600 flex items-center">
{isWorking ? '출근시간: ' : '퇴근시간: '} {getCheckedHour(memberInfo.id)}
</p>
</div>
<button onClick={() => changeWorkingState(memberInfo.id)} className="" >{isWorking ? '퇴근' : '출근'}</button>
</div>
</div>
<div className="h-48 lg:h-auto w-128 lg:w-128 flex-none bg-cover rounded-t lg:rounded-t-none lg:rounded-l text-center overflow-hidden">
</div>
</div>
)
}

export default Card;
2 changes: 2 additions & 0 deletions reactStudy1week/src/components/Card.jsx:Zone.Identifier
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[ZoneTransfer]
ZoneId=3
3 changes: 3 additions & 0 deletions reactStudy1week/src/components/WorkingCheckButtom.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function WorkingCheckButton() {

}
Loading