Merge branch 'fe/lectureRoute' into 'frontend'
[Front-End] feat: 접근할 수 없는 강의 페이지 접근 못하도록 로직 추가 See merge request s11-webmobile1-sub2/S11P12A701!108
This commit is contained in:
commit
a868c6e3f7
@ -68,11 +68,11 @@ const router = createBrowserRouter([
|
||||
element: <LectureCreatePage />,
|
||||
},
|
||||
{
|
||||
path: 'lecture/:lectureId/info',
|
||||
path: 'lecture/:lectureId',
|
||||
element: <LectureInfoPage />,
|
||||
},
|
||||
{
|
||||
path: 'lecture/:lectureId',
|
||||
path: 'lecture/:lectureId/class',
|
||||
element: <LectureLayout />,
|
||||
children: [
|
||||
{
|
||||
|
@ -4,10 +4,21 @@ import styles from './ArticleDetail.module.css';
|
||||
import ArticleDetailAnswer from './ArticleDetailAnswer/ArticleDetailAnswer';
|
||||
import ArticleDetailAnswerInput from './ArticleDetailAnswer/ArticleDetailAnswerInput';
|
||||
import { useState, useEffect } from 'react';
|
||||
import useBoundStore from '../../../store';
|
||||
|
||||
export default function ArticleDetail({ topic, title, author = null, content, answer = null, onDelete, isQna = true }) {
|
||||
export default function ArticleDetail({
|
||||
topic,
|
||||
title,
|
||||
author = null,
|
||||
content,
|
||||
answer = null,
|
||||
onDelete,
|
||||
isMine = false,
|
||||
isQna = true,
|
||||
}) {
|
||||
const [submittedAnswer, setSubmittedAnswer] = useState(answer);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const userType = useBoundStore((state) => state.userType);
|
||||
|
||||
useEffect(() => {
|
||||
setSubmittedAnswer(answer);
|
||||
@ -44,20 +55,24 @@ export default function ArticleDetail({ topic, title, author = null, content, an
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.actionGroup}>
|
||||
<Link
|
||||
className={styles.edit}
|
||||
to={'edit'}
|
||||
state={{ title: title, content: content, answer: answer }}
|
||||
>
|
||||
수정
|
||||
</Link>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.delete}
|
||||
onClick={onDelete}
|
||||
>
|
||||
삭제
|
||||
</button>
|
||||
{(isMine || userType === 'teacher') && (
|
||||
<>
|
||||
<Link
|
||||
className={styles.edit}
|
||||
to={'edit'}
|
||||
state={{ title: title, content: content, answer: answer }}
|
||||
>
|
||||
수정
|
||||
</Link>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.delete}
|
||||
onClick={onDelete}
|
||||
>
|
||||
삭제
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</header>
|
||||
<div>
|
||||
|
@ -15,15 +15,17 @@ export default function ClassInfo({ classTerm, classTime, status = 'NOT_ENROLLED
|
||||
<div className={styles.content}>{classTime}</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={onSubmit}
|
||||
className={styles.button}
|
||||
disabled={status === 'PENDING'}
|
||||
>
|
||||
{status === 'PENDING' && '수강신청 중'}
|
||||
{status === 'ENROLLED' && '강의 상세페이지로 이동'}
|
||||
{status === 'NOT_ENROLLED' && '수강신청'}
|
||||
</button>
|
||||
{status !== 'MANAGED_BY_OTHERS' && (
|
||||
<button
|
||||
onClick={onSubmit}
|
||||
className={styles.button}
|
||||
disabled={status === 'PENDING'}
|
||||
>
|
||||
{status === 'PENDING' && '수강신청 중'}
|
||||
{status === 'ENROLLED' && '강의 상세페이지로 이동'}
|
||||
{status === 'NOT_ENROLLED' && '수강신청'}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import { Outlet, useParams } from 'react-router-dom';
|
||||
import LectureHeader from '../LectureHeader/LectureHeader';
|
||||
import { SideBar, SideLink, SideItem } from '../SideBar';
|
||||
import MaxWidthLayout from './MaxWidthLayout';
|
||||
import { Suspense } from 'react';
|
||||
import { Suspense, useEffect } from 'react';
|
||||
import useBoundStore from '../../store';
|
||||
import { useLectureInfo } from '../../hooks/api/useLectureInfo';
|
||||
import LoadingIndicator from '../LoadingIndicator.jsx/LoadingIndicator';
|
||||
@ -34,6 +34,12 @@ export default function LectureLayout() {
|
||||
time: lecture.time,
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (['NOT_ENROLLED', 'MANAGED_BY_OTHERS', 'PENDING'].includes(lecture.status)) {
|
||||
navigate('..');
|
||||
}
|
||||
}, [lecture.status, navigate]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<LectureHeader
|
||||
|
@ -4,8 +4,12 @@ import SideBar from '../../components/SideBar/SideBar';
|
||||
import SideLink from '../../components/SideBar/SideLink';
|
||||
import { Suspense } from 'react';
|
||||
import LoadingIndicator from '../LoadingIndicator.jsx/LoadingIndicator';
|
||||
import useBoundStore from '../../store';
|
||||
|
||||
export default function MyPageLayout() {
|
||||
const userType = useBoundStore((state) => state.userType);
|
||||
const myLectureTitle = userType === 'student' ? '수강중인 강의' : '내 강의';
|
||||
|
||||
return (
|
||||
<>
|
||||
<MaxWidthLayout hasSideBar>
|
||||
@ -15,7 +19,7 @@ export default function MyPageLayout() {
|
||||
to={''}
|
||||
end
|
||||
>
|
||||
수강중인 강의
|
||||
{myLectureTitle}
|
||||
</SideLink>
|
||||
<SideLink to={'edit'}>개인정보 변경</SideLink>
|
||||
<SideLink to={'changePw'}>비밀번호 변경</SideLink>
|
||||
|
@ -6,7 +6,7 @@ export function useAnswerDelete() {
|
||||
const newAnswer = {
|
||||
answer: null,
|
||||
};
|
||||
return instance.post(`${API_URL}/qna/answer/create/${questionId}`, newAnswer);
|
||||
return instance.post(`${API_URL}/qna/answer/delete/${questionId}`, newAnswer);
|
||||
};
|
||||
|
||||
return { answerDelete };
|
||||
|
@ -14,7 +14,7 @@ export default function StudentHomePage() {
|
||||
{allClasses.map?.((lecture) => (
|
||||
<ClassCard
|
||||
key={lecture.id}
|
||||
path={`/lecture/${lecture.id}/info`}
|
||||
path={`/lecture/${lecture.id}`}
|
||||
img={lecture.image}
|
||||
>
|
||||
{lecture.title}
|
||||
|
@ -3,21 +3,24 @@ import { Link } from 'react-router-dom';
|
||||
import { useMyLectures } from '../../hooks/api/useMyLectures';
|
||||
import CompassIcon from '/src/assets/icons/compass.svg?react';
|
||||
import { STATIC_URL } from '../../constants';
|
||||
import useBoundStore from '../../store';
|
||||
|
||||
export default function LearningLecturesPage() {
|
||||
const { data } = useMyLectures();
|
||||
const onGoingClasses = data?.data ?? [];
|
||||
const hasOnGoingClasses = onGoingClasses.length > 0;
|
||||
const userType = useBoundStore((state) => state.userType);
|
||||
const myLectureTitle = userType === 'student' ? '수강중인 강의' : '내 강의';
|
||||
|
||||
return (
|
||||
<section>
|
||||
<h2 className={styles.title}>수강중인 강의</h2>
|
||||
<h2 className={styles.title}>{myLectureTitle}</h2>
|
||||
<div className={styles.grid}>
|
||||
{hasOnGoingClasses ? (
|
||||
onGoingClasses.map?.((lecture) => (
|
||||
<Link
|
||||
key={lecture.id}
|
||||
to={`/lecture/${lecture.id}`}
|
||||
to={`/lecture/${lecture.id}/class`}
|
||||
className={styles.card}
|
||||
>
|
||||
{lecture.image ? (
|
||||
|
@ -24,7 +24,7 @@ export default function LectureInfoPage() {
|
||||
}
|
||||
|
||||
if (status === 'ENROLLED') {
|
||||
navigate(`/lecture/${lectureId}`);
|
||||
navigate(`/lecture/${lectureId}/class`);
|
||||
}
|
||||
|
||||
if (status === 'NOT_ENROLLED') {
|
||||
|
@ -23,6 +23,7 @@ export default function NoticeDetailPage() {
|
||||
content={notice.content}
|
||||
onDelete={handleDelete}
|
||||
isQna={false}
|
||||
isMine={notice.mine}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ export default function StudentHomePage() {
|
||||
onGoingClasses.map?.((lecture) => (
|
||||
<ClassCard
|
||||
key={lecture.id}
|
||||
path={`/lecture/${lecture.id}`}
|
||||
path={`/lecture/${lecture.id}/class`}
|
||||
img={lecture.image}
|
||||
>
|
||||
{lecture.title}
|
||||
@ -34,7 +34,7 @@ export default function StudentHomePage() {
|
||||
{allClasses.map?.((lecture) => (
|
||||
<ClassCard
|
||||
key={lecture.id}
|
||||
path={`/lecture/${lecture.id}/info`}
|
||||
path={`/lecture/${lecture.id}`}
|
||||
img={lecture.image}
|
||||
>
|
||||
{lecture.title}
|
||||
|
@ -16,7 +16,7 @@ export default function TeacherHomePage() {
|
||||
{onGoingClasses.map((lecture) => (
|
||||
<ClassCard
|
||||
key={lecture.id}
|
||||
path={`/lecture/${lecture.id}`}
|
||||
path={`/lecture/${lecture.id}/class`}
|
||||
img={lecture.image}
|
||||
>
|
||||
{lecture.title}
|
||||
|
@ -5,8 +5,8 @@
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
margin-bottom: 32px;
|
||||
width: 295px;
|
||||
height: 220px;
|
||||
width: 100%;
|
||||
aspect-ratio: 4/3;
|
||||
background-color: var(--background);
|
||||
color: var(--text-color);
|
||||
stroke: var(--text-color);
|
||||
|
Loading…
Reference in New Issue
Block a user