Skip to content

Commit

Permalink
Merge pull request #31 from WASSUP-Project/develop
Browse files Browse the repository at this point in the history
[close #26, close #27] 공지사항, 출석 페이지 화면 보완
  • Loading branch information
YehyeokBang authored Apr 1, 2024
2 parents f3add06 + a5aa5cf commit 145457f
Show file tree
Hide file tree
Showing 8 changed files with 317 additions and 30 deletions.
Binary file removed public/attendance.png
Binary file not shown.
Binary file removed public/noticeEx.png
Binary file not shown.
24 changes: 3 additions & 21 deletions src/app/attendance/page.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,13 @@
import AttendancePad from "@/containers/group/detail/contents/AttendancePad";
import { Button } from "@nextui-org/react";
import Image from "next/image";
import Link from "next/link";

export default function AttendancePage() {
return (
<>
<div
style={{
display: "flex",
justifyContent: "center",
paddingTop: "10rem",
}}
>
<Image
src="/attendance.png"
alt="Image of something relevant"
width={1000}
height={250}
></Image>
</div>
<div
style={{
display: "flex",
justifyContent: "center",
paddingTop: "2rem",
}}
>
<div>
<AttendancePad />
<Button color="primary">
<Link href="/">돌아가기</Link>
</Button>
Expand Down
92 changes: 92 additions & 0 deletions src/containers/group/detail/contents/AttendancePad.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* 헤더 */
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
}

.header img {
width: 80px;
}

.header .userInfo {
display: flex;
align-items: center;
}

.header .userInfo span {
margin-right: 1rem;
}

/* 컨테이너 */
.container {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
height: calc(100vh - 4rem);
/* 헤더 제외 */
padding: 2rem;
background-color: #f5f5f5;
}

/* 번호 입력 칸 */
.inputNumber {
width: 100%;
max-width: 300px;
margin-bottom: 1rem;
}

.inputNumber input {
width: 100%;
padding: 1rem;
font-size: 1.6rem;
border: 1px solid #ddd;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
text-align: center;
}

.inputNumber .errorMessage {
color: red;
font-size: 0.8rem;
margin-top: 0.5rem;
}

/* 넘버 패드 */
.numberPad {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 0.5rem;
width: 100%;
max-width: 300px;
margin-bottom: 1rem;
}

.numberButton {
width: 100%;
height: 50px;
font-size: 1.4rem;
border: 1px solid #ddd;
border-radius: 4px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
cursor: pointer;
}

.previousButton {
background-color: #ddd;
}

/* 버튼 */
.confirmButton {
width: 100%;
max-width: 300px;
height: 50px;
font-size: 1.4rem;
border: none;
border-radius: 4px;
background-color: #000;
color: #fff;
cursor: pointer;
}
72 changes: 72 additions & 0 deletions src/containers/group/detail/contents/AttendancePad.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"use client";

import React, { useState } from "react";
import styles from "./AttendancePad.module.css";

export default function AttendancePad() {
const [inputNumber, setInputNumber] = useState("");
const [errorMessage, setErrorMessage] = useState("");

const handleNumberClick = (number: number) => {
if (inputNumber.length < 4) {
setInputNumber(inputNumber + number);
}
};

const handlePreviousClick = () => {
setInputNumber(inputNumber.slice(0, -1));
};

const handleConfirmClick = () => {
if (inputNumber.length === 4) {
// TODO: API 연동
// 서버에 4자리 숫자 전송
// 서버에서 출석 정보 확인 후 결과 표시
} else {
setErrorMessage("4자리 숫자를 입력하세요.");
}
};

return (
<>
<header className={styles.header}>
<div className={styles.userInfo}>
<span>이름:</span>
</div>
</header>
<div className={styles.container}>
<div className={styles.inputNumber}>
<input
type="number"
value={inputNumber}
maxLength={4}
onChange={(e) => setInputNumber(e.target.value)}
/>
{errorMessage && (
<p className={styles.errorMessage}>{errorMessage}</p>
)}
</div>
<div className={styles.numberPad}>
{Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 0).map((i) => (
<button
key={i}
className={styles.numberButton}
onClick={() => handleNumberClick(i)}
>
{i}
</button>
))}
<button
className={styles.previousButton}
onClick={handlePreviousClick}
>
</button>
</div>
<button className={styles.confirmButton} onClick={handleConfirmClick}>
출석 확인
</button>
</div>
</>
);
}
51 changes: 51 additions & 0 deletions src/containers/group/detail/contents/GroupNotice.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,55 @@
text-align: left;
padding-left: 0.5rem;
padding-bottom: 1.5rem;
}

.button_group {
display: flex;
justify-content: flex-end;
margin-bottom: 1.5rem;
}

.button {
background-color: #007bff;
color: #fff;
border-radius: 0.5rem;
padding: 0.8rem 1.5rem;
cursor: pointer;
transition: background-color 0.2s ease-in-out;
}

.notice_container {
flex-grow: 1;
overflow-y: auto;
}

.notice {
margin-bottom: 1.2rem;
border-radius: 0.5rem;
background-color: #fff;
padding: 1.5rem;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.notice_title {
font-size: 1.4rem;
font-weight: 600;
margin-bottom: 0.5rem;
}

.notice_content {
color: #666;
line-height: 1.6;
}

.notice_date {
font-size: 0.9rem;
color: #999;
margin-top: 1rem;
text-align: right;
}

.empty_notice {
text-align: center;
padding: 2rem 0;
}
107 changes: 99 additions & 8 deletions src/containers/group/detail/contents/GroupNotice.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,111 @@
import Image from "next/image";
"use client";

import React, { useState, useEffect } from "react";
import styles from "./GroupNotice.module.css";
import {
Modal,
ModalContent,
ModalHeader,
ModalBody,
ModalFooter,
useDisclosure,
Button,
} from "@nextui-org/react";

type notice = {
id: number;
title: string;
content: string;
createdAt: string;
};

export default function GroupNotice() {
const [notices, setNotices] = useState<notice[]>([]);
const { isOpen, onOpen, onOpenChange } = useDisclosure();

// 추후 API로 대체
useEffect(() => {
async function fetchNotices() {
// const response = await fetch("/api/notices");
// const data = await response.json();
setNotices([
{
id: 1,
title: "공지사항 제목1",
content: "내용1",
createdAt: "2024-03-23",
},
{
id: 2,
title: "공지사항 제목2",
content: "내용2",
createdAt: "2024-03-26",
},
{
id: 3,
title: "공지사항 제목3",
content: "내용3",
createdAt: "2024-03-30",
},
]);
}

fetchNotices();
}, []);

return (
<>
<h1 className={styles.title}>공지사항</h1>
<div className={styles.container}>
<div>
<Image
src="/noticeEx.png"
alt="Image of something relevant"
width={560}
height={250}
/>
<div className={styles.button_group}>
<Button color="primary" className={styles.button} onClick={onOpen}>
공지 작성
</Button>
</div>
<div className={styles.notice_container}>
<div className={styles.title}>보낸 이력</div>
{notices.length === 0 ? (
<div className={styles.empty_notice}>공지사항이 없습니다.</div>
) : (
notices.map((notice) => (
<div key={notice.id} className={styles.notice}>
<div className={styles.notice_title}>{notice.title}</div>
<div className={styles.notice_content}>{notice.content}</div>
<div className={styles.notice_date}>{notice.createdAt}</div>
</div>
))
)}
</div>
</div>

<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalContent>
{(onClose) => (
<>
<ModalHeader className="flex flex-col gap-0">
메시지 전송
</ModalHeader>
<ModalBody className={styles.modal__body}>
<>
<h3 className={styles.modal__content_Title}>메시지</h3>
<textarea
className={styles.message_textarea}
placeholder="메시지를 입력해주세요."
></textarea>
</>
</ModalBody>
<ModalFooter>
<Button color="secondary" onPress={onClose}>
돌아가기
</Button>
<Button color="primary" onPress={onClose}>
전송하기
</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
</>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
.button {
padding: 5px 10px;
border-radius: 8px;
font-size: 16px;
color: #ffffff;
background-color: #3b82f6;;
}
Expand Down

0 comments on commit 145457f

Please sign in to comment.