Merge branch 'fe/lectureRoute' into 'frontend'

[Front-End] feat: 접근할 수 없는 강의 페이지 접근 못하도록 로직 추가

See merge request s11-webmobile1-sub2/S11P12A701!108
This commit is contained in:
조민우 2024-08-08 14:50:55 +09:00
commit a868c6e3f7
13 changed files with 69 additions and 38 deletions

View File

@ -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: [
{

View File

@ -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,6 +55,8 @@ export default function ArticleDetail({ topic, title, author = null, content, an
</div>
</div>
<div className={styles.actionGroup}>
{(isMine || userType === 'teacher') && (
<>
<Link
className={styles.edit}
to={'edit'}
@ -58,6 +71,8 @@ export default function ArticleDetail({ topic, title, author = null, content, an
>
삭제
</button>
</>
)}
</div>
</header>
<div>

View File

@ -15,6 +15,7 @@ export default function ClassInfo({ classTerm, classTime, status = 'NOT_ENROLLED
<div className={styles.content}>{classTime}</div>
</div>
</div>
{status !== 'MANAGED_BY_OTHERS' && (
<button
onClick={onSubmit}
className={styles.button}
@ -24,6 +25,7 @@ export default function ClassInfo({ classTerm, classTime, status = 'NOT_ENROLLED
{status === 'ENROLLED' && '강의 상세페이지로 이동'}
{status === 'NOT_ENROLLED' && '수강신청'}
</button>
)}
</div>
);
}

View File

@ -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

View File

@ -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>

View File

@ -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 };

View File

@ -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}

View File

@ -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 ? (

View File

@ -24,7 +24,7 @@ export default function LectureInfoPage() {
}
if (status === 'ENROLLED') {
navigate(`/lecture/${lectureId}`);
navigate(`/lecture/${lectureId}/class`);
}
if (status === 'NOT_ENROLLED') {

View File

@ -23,6 +23,7 @@ export default function NoticeDetailPage() {
content={notice.content}
onDelete={handleDelete}
isQna={false}
isMine={notice.mine}
/>
);
}

View File

@ -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}

View File

@ -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}

View File

@ -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);