Merge branch 'fe/infiniteScroll' into 'frontend'
[Front-End] 공지사항, 자유게시판에 무한스크롤 추가 See merge request s11-webmobile1-sub2/S11P12A701!158
This commit is contained in:
commit
d755840501
@ -31,7 +31,6 @@ export default function ArticleDetailAnswerInput({ onSubmit, initialAnswer = '',
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
console.log(isEditing);
|
||||
if (isEditing) {
|
||||
await answerEdit(questionId, answer);
|
||||
} else {
|
||||
@ -40,8 +39,6 @@ export default function ArticleDetailAnswerInput({ onSubmit, initialAnswer = '',
|
||||
onSubmit(answer);
|
||||
};
|
||||
|
||||
console.log(answer);
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
|
@ -3,9 +3,7 @@
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
width: 100%;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 16px;
|
||||
padding: 12px 16px;
|
||||
padding: 12px 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@ -43,6 +41,7 @@
|
||||
line-height: 1.4;
|
||||
margin: 0;
|
||||
color: var(--text-color);
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.input {
|
||||
|
@ -56,18 +56,22 @@ export default function FreeboardDetail({ topic, title, author, content, onDelet
|
||||
<div>
|
||||
<p className={styles.content}>{content}</p>
|
||||
</div>
|
||||
{comments &&
|
||||
comments.map((comment) => (
|
||||
<FreeboardComment
|
||||
key={comment.id}
|
||||
content={comment.content}
|
||||
author={comment.name}
|
||||
commentId={comment.id}
|
||||
isMine={comment.mine}
|
||||
onDeleteSubmit={refetch}
|
||||
onEditSubmit={refetch}
|
||||
/>
|
||||
))}
|
||||
|
||||
{comments && (
|
||||
<div className={styles.commentWrapper}>
|
||||
{comments.map((comment) => (
|
||||
<FreeboardComment
|
||||
key={comment.id}
|
||||
content={comment.content}
|
||||
author={comment.name}
|
||||
commentId={comment.id}
|
||||
isMine={comment.mine}
|
||||
onDeleteSubmit={refetch}
|
||||
onEditSubmit={refetch}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<FreeboardCommentInput onCommentSubmit={handleCommentSubmit} />
|
||||
</div>
|
||||
);
|
||||
|
@ -114,3 +114,11 @@
|
||||
.delete {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
.commentWrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: 1px solid var(--border-color);
|
||||
margin-top: 10px;
|
||||
padding-top: 18px;
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
.articleLink {
|
||||
border-radius: 8px;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
gap: 20px;
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
padding: 16px 20px;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.25s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.articleLink:hover {
|
||||
@ -17,9 +19,13 @@
|
||||
line-height: 1.4;
|
||||
font-weight: 400;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.date {
|
||||
flex-shrink: 0;
|
||||
font-size: 14px;
|
||||
line-height: 1.4;
|
||||
font-weight: 400;
|
||||
|
@ -1,27 +0,0 @@
|
||||
import styles from './ChatInput.module.css';
|
||||
import { useRef } from 'react';
|
||||
|
||||
export default function ChattingInput() {
|
||||
// TODO: 채팅이 넘어갈 시 줄바꿈이 되도록 수정
|
||||
// TODO: ㅁ 을 아이콘으로 변경
|
||||
const message = useRef('');
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
// TODO: 실제 메시지 전송 기능 추가
|
||||
console.log(message.current.value);
|
||||
message.current.value = '';
|
||||
};
|
||||
return (
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className={styles.chattingInput}
|
||||
>
|
||||
<input
|
||||
ref={message}
|
||||
className={styles.input}
|
||||
placeholder="메시지를 입력하세요"
|
||||
/>
|
||||
<div onClick={handleSubmit}>ㅁ</div>
|
||||
</form>
|
||||
);
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
.chattingInput {
|
||||
border-radius: 9999px;
|
||||
background-color: var(--background);
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 12px 16px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.input {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 1;
|
||||
color: var(--text-color);
|
||||
border: 0;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input::placeholder {
|
||||
color: var(--text-color-tertiary);
|
||||
}
|
@ -1 +0,0 @@
|
||||
export { default as ChatInput } from './ChatInput';
|
@ -12,6 +12,7 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
padding: 16px;
|
||||
|
||||
& > .quizButton {
|
||||
|
@ -1,60 +0,0 @@
|
||||
import styles from './CreateClass.module.css';
|
||||
import { useRef } from 'react';
|
||||
|
||||
export default function CreateClass() {
|
||||
// TODO: ㅁ 아이콘으로 변경
|
||||
const classTime = useRef('');
|
||||
const numOfLecture = useRef('');
|
||||
const significant = useRef('');
|
||||
|
||||
const handleSubmit = () => {
|
||||
// TODO : 강의 생성 기능 작성
|
||||
const payload = {
|
||||
classTime: classTime.current.value,
|
||||
numOfLecture: numOfLecture.current.value,
|
||||
significant: significant.current.value,
|
||||
};
|
||||
alert(`특이사항 : ${payload.significant}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<form
|
||||
className={styles.createClass}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<div className={styles.inputField}>
|
||||
<label className={styles.label}>수업 시간</label>
|
||||
<input
|
||||
className={styles.input}
|
||||
ref={classTime}
|
||||
type="text"
|
||||
placeholder="수업 시간을 입력하세요"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.inputField}>
|
||||
<label className={styles.label}>강의 수</label>
|
||||
<input
|
||||
className={styles.input}
|
||||
ref={numOfLecture}
|
||||
type="text"
|
||||
placeholder="총 강의 수를 입력하세요"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.inputField}>
|
||||
<label className={styles.label}>특이사항</label>
|
||||
<textarea
|
||||
ref={significant}
|
||||
className={styles.textarea}
|
||||
placeholder="이 수업만의 특이사항이 있다면 입력하세요"
|
||||
></textarea>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className={styles.button}
|
||||
>
|
||||
<div>ㅁ</div>
|
||||
<div className={styles.buttonText}>글 쓰기</div>
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
.createClass {
|
||||
background: var(--background-color);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
.inputField {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: var(--text-color);
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.input {
|
||||
background: var(--background-color);
|
||||
padding: 20px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
font-size: 20px;
|
||||
line-height: 1.2;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.input::placeholder {
|
||||
color: var(--text-color-tertiary);
|
||||
}
|
||||
|
||||
.textarea {
|
||||
padding: 20px;
|
||||
height: 150px;
|
||||
background: var(--background-color);
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.textarea::placeholder {
|
||||
color: var(--text-color-tertiary);
|
||||
}
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 16px 24px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--primary-color);
|
||||
background-color: var(--primary-color);
|
||||
color: var(--on-primary);
|
||||
gap: 8px;
|
||||
align-self: end;
|
||||
}
|
||||
|
||||
.buttonText {
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
font-weight: 700;
|
||||
}
|
@ -1 +0,0 @@
|
||||
export { default as CreateClass } from './CreateClass';
|
@ -0,0 +1,33 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
export default function IntersectionArea({ onObserve, once = false }) {
|
||||
const ref = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const callback = (entries, observer) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
onObserve();
|
||||
if (once) {
|
||||
observer.disconnect();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
const observer = new IntersectionObserver(callback, {
|
||||
root: null,
|
||||
rootMargin: '0px',
|
||||
threshold: 0.5,
|
||||
});
|
||||
|
||||
if (ref.current) {
|
||||
observer.observe(ref.current);
|
||||
}
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, [onObserve, once]);
|
||||
|
||||
return <div ref={ref} />;
|
||||
}
|
1
frontend/src/components/IntersectionArea/index.js
Normal file
1
frontend/src/components/IntersectionArea/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default as IntersectionArea } from './IntersectionArea';
|
@ -19,6 +19,7 @@
|
||||
}
|
||||
|
||||
& > main {
|
||||
min-width: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ export default function LectureForm({ title, topic, to = '..', initialValues = {
|
||||
const timeRef = useRef('');
|
||||
const imageFileRef = useRef(null);
|
||||
|
||||
// 초기 값 설정
|
||||
useEffect(() => {
|
||||
if (initialValues.title) titleRef.current.value = initialValues.title;
|
||||
if (initialValues.description) descriptionRef.current.value = initialValues.description;
|
||||
@ -60,7 +59,10 @@ export default function LectureForm({ title, topic, to = '..', initialValues = {
|
||||
</Link>
|
||||
<div className={styles.title}>{topic}</div>
|
||||
</header>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<form
|
||||
onSubmit={handleSubmit}
|
||||
className={styles.form}
|
||||
>
|
||||
<div className={styles.inputField}>
|
||||
<label className={styles.label}>강의명</label>
|
||||
<input
|
||||
@ -89,16 +91,24 @@ export default function LectureForm({ title, topic, to = '..', initialValues = {
|
||||
</div>
|
||||
<div className={styles.inputField}>
|
||||
<label className={styles.label}>강의 기간</label>
|
||||
<input
|
||||
className={styles.input}
|
||||
ref={startDateRef}
|
||||
type="date"
|
||||
/>
|
||||
<input
|
||||
className={styles.input}
|
||||
ref={endDateRef}
|
||||
type="date"
|
||||
/>
|
||||
<div className={styles.dateWrapper}>
|
||||
<div className={styles.date}>
|
||||
<input
|
||||
className={styles.input}
|
||||
ref={startDateRef}
|
||||
type="date"
|
||||
/>
|
||||
<span className={styles.label}>부터</span>
|
||||
</div>
|
||||
<div className={styles.date}>
|
||||
<input
|
||||
className={styles.input}
|
||||
ref={endDateRef}
|
||||
type="date"
|
||||
/>
|
||||
<span className={styles.label}>까지</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.inputField}>
|
||||
<label className={styles.label}>수업 시간</label>
|
||||
@ -117,6 +127,7 @@ export default function LectureForm({ title, topic, to = '..', initialValues = {
|
||||
type="file"
|
||||
ref={imageFileRef}
|
||||
accept=".png, .jpg, .jpeg"
|
||||
className={styles.input}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
@ -32,6 +32,33 @@
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.dateWrapper {
|
||||
display: flex;
|
||||
gap: 40px;
|
||||
}
|
||||
|
||||
.date {
|
||||
display: flex;
|
||||
justify-content: stretch;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
|
||||
& > input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
& > span {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.inputField {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -47,11 +74,11 @@
|
||||
|
||||
.input {
|
||||
background: var(--background-color);
|
||||
padding: 20px;
|
||||
padding: 16px;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
font-size: 20px;
|
||||
line-height: 1.2;
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@ -60,7 +87,7 @@
|
||||
}
|
||||
|
||||
.textarea {
|
||||
padding: 20px;
|
||||
padding: 16px;
|
||||
height: 80px;
|
||||
background: var(--background-color);
|
||||
border: 1px solid var(--border-color);
|
||||
|
@ -116,7 +116,7 @@ export default function LiveRoom() {
|
||||
<span>{participants.length}명</span>
|
||||
</div>
|
||||
</header>
|
||||
<div className="lk-video-conference">
|
||||
<div className={`lk-video-conference ${styles.videoRoom}`}>
|
||||
<LayoutContextProvider value={layoutContext}>
|
||||
<div className="lk-video-conference-inner">
|
||||
{!focusTrack ? (
|
||||
|
@ -30,3 +30,7 @@
|
||||
line-height: 1.4;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.videoRoom {
|
||||
height: calc(100% - 48px) !important;
|
||||
}
|
||||
|
@ -16,7 +16,10 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 16px;
|
||||
white-space: pre-line;
|
||||
word-break: break-word;
|
||||
box-sizing: border-box;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.header {
|
||||
|
@ -2,7 +2,6 @@ import styles from './QuizCard.module.css';
|
||||
import { STATIC_URL } from '../../constants';
|
||||
|
||||
export default function QuizDetailCard({ index, question, answer, image, choices, userAnswer = null, correct = true }) {
|
||||
console.log(correct);
|
||||
return (
|
||||
<div className={`${styles.card} ${!correct && styles.incorrect}`}>
|
||||
<div className={styles.header}>
|
||||
|
@ -16,7 +16,6 @@ export default function QuizsetForm({ headerTitle, topic, to, onSubmit, initialV
|
||||
setTitle(initialValue.title || '');
|
||||
setQuizzes(initialValue.quizzes || []);
|
||||
setQuizId(initialValue.quizzes ? initialValue.quizzes[initialValue.quizzes.length - 1].id + 1 : 0);
|
||||
console.log(initialValue.quizzes.length);
|
||||
}
|
||||
}, [initialValue]);
|
||||
|
||||
@ -79,7 +78,7 @@ export default function QuizsetForm({ headerTitle, topic, to, onSubmit, initialV
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className={`${styles.button} ${styles.add} ${styles.create}`}
|
||||
className={`${styles.button} ${styles.add}`}
|
||||
>
|
||||
<EditIcon />
|
||||
<div>퀴즈 생성하기</div>
|
||||
|
@ -109,10 +109,6 @@
|
||||
stroke: var(--on-primary);
|
||||
}
|
||||
|
||||
.create {
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.edit {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ export default function QuizModal({ startQuiz, quizSets, closeModal }) {
|
||||
<li
|
||||
key={quizSet.quizSetId}
|
||||
onClick={() => {
|
||||
console.log(quizSet.quizSetId);
|
||||
startQuiz(quizSet.quizSetId);
|
||||
closeModal();
|
||||
}}
|
||||
|
@ -91,4 +91,5 @@
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.25s;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import styles from './QuizsetDetail.module.css';
|
||||
import { QuizDetailCard } from '../QuizForm';
|
||||
|
||||
export default function QuizsetDetail({ topic, title, quizzes = [], onDelete, onEdit, tested = false }) {
|
||||
console.log('topic', topic, 'title', title, 'quizzes', quizzes);
|
||||
return (
|
||||
<div className={styles.quizsetDetail}>
|
||||
<header className={styles.header}>
|
||||
|
@ -2,3 +2,4 @@ export const API_URL = import.meta.env.VITE_API_URL;
|
||||
export const ROOM_URL = import.meta.env.VITE_ROOM_URL;
|
||||
export const CHAT_URL = import.meta.env.VITE_CHAT_URL;
|
||||
export const STATIC_URL = import.meta.env.VITE_STATIC_URL;
|
||||
export const PAGE_SIZE = 20;
|
||||
|
@ -40,12 +40,7 @@ export function useAuth() {
|
||||
const logout = () => {
|
||||
return instance
|
||||
.post(`${API_URL}/user/logout`)
|
||||
.then((response) => {
|
||||
console.log(response);
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
})
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
setUserType(null);
|
||||
setToken(null);
|
||||
@ -66,7 +61,6 @@ export function useAuth() {
|
||||
newPassword: newPw,
|
||||
newPasswordCheck: newPwCheck,
|
||||
};
|
||||
console.log(passwordBody);
|
||||
return instance.put(`${API_URL}/user/updatepassword`, passwordBody);
|
||||
};
|
||||
|
||||
|
@ -1,10 +1,17 @@
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
import { useSuspenseInfiniteQuery } from '@tanstack/react-query';
|
||||
import instance from '../../utils/axios/instance';
|
||||
import { API_URL } from '../../constants';
|
||||
import { API_URL, PAGE_SIZE } from '../../constants';
|
||||
|
||||
export function useFreeboards(lectureId, page = 0) {
|
||||
return useSuspenseQuery({
|
||||
return useSuspenseInfiniteQuery({
|
||||
queryKey: ['freeboardlist', lectureId, page],
|
||||
queryFn: () => instance.get(`${API_URL}/board?lectureId=${lectureId}&category=freeboard&pageNo=${page}`),
|
||||
queryFn: ({ pageParam = 0 }) =>
|
||||
instance.get(`${API_URL}/board?lectureId=${lectureId}&category=freeboard&pageNo=${pageParam}`),
|
||||
getNextPageParam: (lastPage, allPages) => {
|
||||
if (lastPage.data.length < PAGE_SIZE) {
|
||||
return undefined;
|
||||
}
|
||||
return allPages.length + 1;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ import { API_URL } from '../../constants';
|
||||
|
||||
export function useLectureCreate() {
|
||||
const lectureCreate = (formData) => {
|
||||
// return instance.post(`${API_URL}/lecture`, lectureObject, image);
|
||||
return instance.post(`${API_URL}/lecture`, formData, {
|
||||
headers: {
|
||||
'Content-type': 'multipart/form-data',
|
||||
|
@ -7,7 +7,7 @@ export function useNoticeEdit() {
|
||||
title,
|
||||
content,
|
||||
};
|
||||
console.log(newNotice);
|
||||
|
||||
return instance.put(`${API_URL}/board/${boardId}`, newNotice);
|
||||
};
|
||||
|
||||
|
@ -1,10 +1,17 @@
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
import { useSuspenseInfiniteQuery } from '@tanstack/react-query';
|
||||
import instance from '../../utils/axios/instance';
|
||||
import { API_URL } from '../../constants';
|
||||
import { API_URL, PAGE_SIZE } from '../../constants';
|
||||
|
||||
export function useNotices(lectureId, page = 0) {
|
||||
return useSuspenseQuery({
|
||||
queryKey: ['noticelist', lectureId, page],
|
||||
queryFn: () => instance.get(`${API_URL}/board?lectureId=${lectureId}&category=announcement&pageNo=${page}`),
|
||||
export function useNotices(lectureId) {
|
||||
return useSuspenseInfiniteQuery({
|
||||
queryKey: ['noticelist', lectureId],
|
||||
queryFn: ({ pageParam = 0 }) =>
|
||||
instance.get(`${API_URL}/board?lectureId=${lectureId}&category=announcement&pageNo=${pageParam}`),
|
||||
getNextPageParam: (lastPage, allPages) => {
|
||||
if (lastPage.data.length < PAGE_SIZE) {
|
||||
return undefined;
|
||||
}
|
||||
return allPages.length + 1;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ import { API_URL } from '../../constants';
|
||||
|
||||
export function usePasswordReset() {
|
||||
const sendEmail = (email) => {
|
||||
console.log(email);
|
||||
return instance.post(`${API_URL}/mail/sendcode?email=${email}`);
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,6 @@ import { useLectures } from '../../hooks/api/useLectures';
|
||||
export default function StudentHomePage() {
|
||||
const { data: allLectures } = useLectures();
|
||||
const allClasses = allLectures?.data ?? [];
|
||||
console.log(allClasses);
|
||||
|
||||
return (
|
||||
<MaxWidthLayout>
|
||||
|
@ -2,25 +2,28 @@ import { ArticleLink } from '../../components/ArticleLink';
|
||||
import ArticleBoard from '../../components/ArticleBoard/ArticleBoard';
|
||||
import { useFreeboards } from '../../hooks/api/useFreeboards';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import IntersectionArea from '../../components/IntersectionArea/IntersectionObserver';
|
||||
|
||||
export default function NoticeListPage() {
|
||||
const { lectureId } = useParams();
|
||||
const { data } = useFreeboards(lectureId);
|
||||
const notices = data?.data;
|
||||
const { data, fetchNextPage, hasNextPage } = useFreeboards(lectureId);
|
||||
const articles = data?.pages.flatMap((page) => page.data);
|
||||
|
||||
return (
|
||||
<ArticleBoard
|
||||
title="자유게시판"
|
||||
canCreate={true}
|
||||
>
|
||||
{notices.map?.((notice) => (
|
||||
<ArticleLink
|
||||
key={`${notice.id}`}
|
||||
title={notice.title}
|
||||
sub={`${new Date(notice.createdAt).toLocaleDateString()} ${new Date(notice.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`}
|
||||
to={`${notice.id}`}
|
||||
/>
|
||||
))}
|
||||
{articles.length &&
|
||||
articles.map?.((notice) => (
|
||||
<ArticleLink
|
||||
key={`${notice.id}`}
|
||||
title={notice.title}
|
||||
sub={`${new Date(notice.createdAt).toLocaleDateString()} ${new Date(notice.createdAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`}
|
||||
to={`${notice.id}`}
|
||||
/>
|
||||
))}
|
||||
{hasNextPage && <IntersectionArea onObserve={() => fetchNextPage()} />}
|
||||
</ArticleBoard>
|
||||
);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import { useQnas } from '../../hooks/api/useQnas';
|
||||
export default function LearningLectureDetailPage() {
|
||||
const { lectureId } = useParams();
|
||||
const { data: noticesData } = useNotices(lectureId);
|
||||
const notices = noticesData?.data.slice(0, 3);
|
||||
const notices = noticesData.pages[0]?.data.slice(0, 3);
|
||||
const { data: qnasData } = useQnas(lectureId);
|
||||
const questions = qnasData?.data.slice(0, 3);
|
||||
|
||||
|
@ -10,15 +10,12 @@ export default function LecutreEditPage() {
|
||||
const navigate = useNavigate();
|
||||
const { lectureEdit } = useLectureEdit();
|
||||
|
||||
const handleSubmit = async (lectureObject) => {
|
||||
const response = await lectureEdit(lectureId, lectureObject)
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
const handleSubmit = async (lectureObject) =>
|
||||
await lectureEdit(lectureId, lectureObject)
|
||||
.then(() => {
|
||||
navigate('..');
|
||||
})
|
||||
.catch((err) => console.log(err));
|
||||
console.log(response?.data);
|
||||
};
|
||||
.catch(() => {});
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -33,9 +33,7 @@ export default function LectureInfoPage() {
|
||||
window.alert('강사가 수강신청 수락시 수업이 시작됩니다.');
|
||||
navigate('/');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
.catch(() => {});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -16,8 +16,6 @@ export default function MyInfoChangePage() {
|
||||
await updateInfo(username, useremail)
|
||||
.then(() => navigate('/'))
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
console.log(err.response.data);
|
||||
if (err.response.data === '이미 사용 중인 이메일입니다.') {
|
||||
setUsingEmail(true);
|
||||
}
|
||||
|
@ -3,11 +3,12 @@ import ArticleBoard from '../../components/ArticleBoard/ArticleBoard';
|
||||
import { useNotices } from '../../hooks/api/useNotices';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import useBoundStore from '../../store';
|
||||
import IntersectionArea from '../../components/IntersectionArea/IntersectionObserver';
|
||||
|
||||
export default function NoticeListPage() {
|
||||
const { lectureId } = useParams();
|
||||
const { data } = useNotices(lectureId);
|
||||
const notices = data?.data;
|
||||
const { data, fetchNextPage, hasNextPage } = useNotices(lectureId);
|
||||
const notices = data?.pages.flatMap((page) => page.data);
|
||||
const userType = useBoundStore((state) => state.userType);
|
||||
|
||||
return (
|
||||
@ -24,6 +25,7 @@ export default function NoticeListPage() {
|
||||
to={`${notice.id}`}
|
||||
/>
|
||||
))}
|
||||
{hasNextPage && <IntersectionArea onObserve={() => fetchNextPage()} />}
|
||||
</ArticleBoard>
|
||||
);
|
||||
}
|
||||
|
@ -9,14 +9,11 @@ export default function PasswordChangePage() {
|
||||
const { updatePassword } = useAuth();
|
||||
const handleSubmit = async (currentPw, newPw, newPwCheck) => {
|
||||
await updatePassword(currentPw, newPw, newPwCheck)
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
.then(() => {
|
||||
navigate('/');
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err.response.data);
|
||||
if (err.response.data === 'Current password is incorrect') {
|
||||
console.log('현재 비밀번호 에러');
|
||||
setPwError(true);
|
||||
}
|
||||
});
|
||||
|
@ -21,14 +21,11 @@ export default function PasswordResetPage() {
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
setAuthError(false);
|
||||
console.log(authNumRef.current.value, email);
|
||||
verify(authNumRef.current.value, email)
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
.then(() => {
|
||||
setSentAuthNum(true);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
if (err.message === 'Request failed with status code 404') {
|
||||
setAuthError(true);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { AuthForm, InputBox } from '../../components/AuthForm';
|
||||
import { useRef, useState, useEffect } from 'react';
|
||||
import { useRef, useState } from 'react';
|
||||
import styles from './PasswordResetPage.module.css';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { usePasswordReset } from '../../hooks/api/usePasswordReset';
|
||||
@ -11,24 +11,14 @@ export default function PasswordResetPage() {
|
||||
|
||||
const { sendEmail } = usePasswordReset();
|
||||
|
||||
useEffect(() => {
|
||||
if (emailSent) {
|
||||
console.log('Updated emailSent:', emailSent);
|
||||
}
|
||||
}, [emailSent]);
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
setNotFound(false);
|
||||
await sendEmail(emailRef.current.value)
|
||||
.then(() => {
|
||||
const email = emailRef.current.value;
|
||||
console.log(email);
|
||||
setEmailSent(email);
|
||||
console.log(emailSent);
|
||||
setEmailSent(emailRef.current.value);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
if (err.message === 'Request failed with status code 404') {
|
||||
setNotFound(true);
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ export default function QuestionListPage() {
|
||||
const questions = data?.data;
|
||||
const userType = useBoundStore((state) => state.userType);
|
||||
|
||||
console.log(questions);
|
||||
return (
|
||||
<ArticleBoard
|
||||
title="Q&A"
|
||||
|
@ -10,15 +10,14 @@ export default function QuizsetDetailPage() {
|
||||
const { data } = useTeacherQuizsetDetail(quizsetId);
|
||||
const quizset = data.data;
|
||||
const tested = quizset.tested;
|
||||
console.log(tested);
|
||||
const handleEdit = () => {
|
||||
navigate('edit', { state: { initialValue: quizset } });
|
||||
};
|
||||
|
||||
const handleDelete = async () => {
|
||||
await quizsetDelete(quizsetId);
|
||||
navigate('..');
|
||||
};
|
||||
|
||||
return (
|
||||
<QuizsetDetail
|
||||
topic={'퀴즈 목록'}
|
||||
|
@ -9,7 +9,6 @@ export default function QuizsetEditPage() {
|
||||
const location = useLocation();
|
||||
const initialValue = location.state.initialValue;
|
||||
const { quizsetEdit } = useQuizsetEdit();
|
||||
console.log(initialValue);
|
||||
const handleSubmit = async (e, title, quizzes) => {
|
||||
e.preventDefault();
|
||||
|
||||
@ -42,10 +41,6 @@ export default function QuizsetEditPage() {
|
||||
}
|
||||
});
|
||||
|
||||
formData.forEach((value, key) => {
|
||||
console.log(`FormData - Key: ${key}, Value:`, value);
|
||||
});
|
||||
|
||||
await quizsetEdit(formData);
|
||||
navigate('..');
|
||||
};
|
||||
|
@ -2,14 +2,12 @@ import { ArticleLink } from '../../components/ArticleLink';
|
||||
import ArticleBoard from '../../components/ArticleBoard/ArticleBoard';
|
||||
import { useQuizsets } from '../../hooks/api/useQuizsets';
|
||||
import { useParams } from 'react-router-dom';
|
||||
// import useBoundStore from '../../store';
|
||||
|
||||
export default function QuizsetListPage() {
|
||||
const { lectureId } = useParams();
|
||||
const { data } = useQuizsets(lectureId);
|
||||
const quizsets = data?.data ?? [];
|
||||
// const userType = useBoundStore((state) => state.userType);
|
||||
console.log(quizsets);
|
||||
|
||||
return (
|
||||
<ArticleBoard
|
||||
title="퀴즈 목록"
|
||||
|
@ -8,7 +8,6 @@ export default function QuizsetWritePage() {
|
||||
|
||||
const handleSubmit = async (e, title, quizzes) => {
|
||||
e.preventDefault();
|
||||
console.log(quizzes);
|
||||
if (quizzes.length === 0) {
|
||||
window.alert('퀴즈가 없는 퀴즈셋은 생성할 수 없습니다');
|
||||
return;
|
||||
|
@ -8,7 +8,6 @@ export default function StudentReportDetailPage() {
|
||||
const { lectureId, reportId } = useParams();
|
||||
const { data } = useStudentReportDetail(reportId);
|
||||
const report = data.data;
|
||||
console.log(report);
|
||||
const { allCount, correctCount, quizzes, title } = report;
|
||||
const score = Math.round((100 * correctCount) / allCount);
|
||||
return (
|
||||
|
@ -1,5 +1,3 @@
|
||||
// userType : null, 'teacher', 'student'
|
||||
|
||||
export const userTypeSlice = (set) => ({
|
||||
userType: null,
|
||||
setUserType: (userType) => set({ userType }),
|
||||
|
@ -33,16 +33,12 @@ instance.interceptors.response.use(
|
||||
.then((response) => {
|
||||
const { accessToken } = response.data;
|
||||
|
||||
console.log(accessToken);
|
||||
useBoundStore.setState({ token: accessToken });
|
||||
error.config.headers.Authorization = `${accessToken}`;
|
||||
return instance(error.config);
|
||||
})
|
||||
.catch((error) => {
|
||||
useBoundStore.setState({ token: null, userType: null });
|
||||
console.log(error);
|
||||
console.log('---로그아웃----');
|
||||
// TODO: redirect to home
|
||||
return Promise.reject(error);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user