Merge branch 'fe/designs' into 'frontend'
Fe/designs See merge request s11-webmobile1-sub2/S11P12A701!56
This commit is contained in:
commit
16a0c8740d
8
frontend/src/assets/icons/compass.svg
Normal file
8
frontend/src/assets/icons/compass.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<svg width="49" height="49" viewBox="0 0 49 49" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Compass">
|
||||
<g id="Icon">
|
||||
<path d="M24.5 44.5C35.5457 44.5 44.5 35.5457 44.5 24.5C44.5 13.4543 35.5457 4.5 24.5 4.5C13.4543 4.5 4.5 13.4543 4.5 24.5C4.5 35.5457 13.4543 44.5 24.5 44.5Z" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M32.98 16.02L28.74 28.74L16.02 32.98L20.26 20.26L32.98 16.02Z" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 510 B |
5
frontend/src/assets/icons/plus.svg
Normal file
5
frontend/src/assets/icons/plus.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg width="49" height="49" viewBox="0 0 49 49" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g id="Plus circle">
|
||||
<path id="Icon" d="M24.5 16.5V32.5M16.5 24.5H32.5M44.5 24.5C44.5 35.5457 35.5457 44.5 24.5 44.5C13.4543 44.5 4.5 35.5457 4.5 24.5C4.5 13.4543 13.4543 4.5 24.5 4.5C35.5457 4.5 44.5 13.4543 44.5 24.5Z" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 395 B |
@ -1,5 +1,6 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import styles from './ClassCard.module.css';
|
||||
import CompassIcon from '/src/assets/icons/compass.svg?react';
|
||||
|
||||
export default function ClassCard({ img, path, children }) {
|
||||
return (
|
||||
@ -7,11 +8,17 @@ export default function ClassCard({ img, path, children }) {
|
||||
to={path}
|
||||
className={styles.card}
|
||||
>
|
||||
{img ? (
|
||||
<img
|
||||
src={img}
|
||||
alt="강의 이미지"
|
||||
className={styles.thumbnail}
|
||||
/>
|
||||
) : (
|
||||
<div className={styles.thumbnail}>
|
||||
<CompassIcon />
|
||||
</div>
|
||||
)}
|
||||
<div>{children}</div>
|
||||
</Link>
|
||||
);
|
||||
|
@ -9,9 +9,13 @@
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 295px;
|
||||
height: 220px;
|
||||
border-radius: 20px;
|
||||
background-color: var(--background-secondary);
|
||||
stroke: var(--text-color);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
@ -115,7 +115,10 @@ export default function LiveRoom() {
|
||||
</FocusLayoutContainer>
|
||||
</div>
|
||||
)}
|
||||
<ControlBar controls={{ chat: false, leave: false, screenShare: role === '강사' }} />
|
||||
<ControlBar
|
||||
variation="minimal"
|
||||
controls={{ chat: false, leave: true, screenShare: role === '강사' }}
|
||||
/>
|
||||
</div>
|
||||
<ChatRoom />
|
||||
</LayoutContextProvider>
|
||||
|
@ -18,7 +18,7 @@
|
||||
.groupList {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
gap: 8px;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
@ -15,5 +15,4 @@
|
||||
|
||||
.active {
|
||||
font-weight: 700;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||
import instance from '../../utils/axios/instance';
|
||||
import { API_URL } from '../../constants';
|
||||
|
||||
export function useNotices(lectureId, page = 0) {
|
||||
return useQuery({
|
||||
return useSuspenseQuery({
|
||||
queryKey: ['noticelist', lectureId, page],
|
||||
queryFn: () => instance.get(`${API_URL}/board?lectureId=${lectureId}&category=announcement&pageNo=${page}`),
|
||||
});
|
||||
|
@ -1,31 +1,29 @@
|
||||
import { LiveRoom } from '../../components/LiveRoom';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { LiveKitRoom } from '@livekit/components-react';
|
||||
import instance from '../../utils/axios/instance';
|
||||
import { API_URL, ROOM_URL } from '../../constants';
|
||||
import useBoundStore from '../../store';
|
||||
import '@livekit/components-styles';
|
||||
import LoadingIndicator from '../../components/LoadingIndicator.jsx/LoadingIndicator';
|
||||
|
||||
export default function LivePage() {
|
||||
const { roomId } = useParams();
|
||||
const [liveToken, setLiveToken] = useState(null);
|
||||
const generateToken = useCallback(async () => {
|
||||
await instance.post(`${API_URL}/video/makeroom/${roomId}`);
|
||||
const { data } = await instance.post(`${API_URL}/video/joinroom/${roomId}`);
|
||||
const { data } = await instance.post(`${API_URL}/video/joinroom/${roomId}`).catch(() => {
|
||||
alert('방에 입장할 수 없습니다.');
|
||||
});
|
||||
|
||||
return data.token;
|
||||
}, [roomId]);
|
||||
|
||||
const liveToken = useBoundStore((state) => state.liveToken);
|
||||
|
||||
useEffect(() => {
|
||||
if (!liveToken) {
|
||||
generateToken().then((token) => {
|
||||
useBoundStore.setState({ liveToken: token });
|
||||
setLiveToken(token);
|
||||
});
|
||||
}
|
||||
}, [generateToken, liveToken]);
|
||||
}, [generateToken]);
|
||||
|
||||
return liveToken ? (
|
||||
<LiveKitRoom
|
||||
@ -33,6 +31,9 @@ export default function LivePage() {
|
||||
serverUrl={ROOM_URL}
|
||||
connect={true}
|
||||
data-lk-theme="default"
|
||||
onDisconnected={() => {
|
||||
instance.post(`${API_URL}/video/deleteroom/${roomId}`).catch(() => {});
|
||||
}}
|
||||
>
|
||||
<LiveRoom />
|
||||
</LiveKitRoom>
|
||||
|
@ -1,17 +1,19 @@
|
||||
import styles from './TeacherHomePage.module.css';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ClassCard } from '../../components/ClassCard';
|
||||
import { ClassGrid } from '../../components/ClassGrid';
|
||||
import { MaxWidthLayout } from '../../components/Layout';
|
||||
import { useMyLectures } from '../../hooks/api/useMyLectures';
|
||||
import PlusIcon from '/src/assets/icons/plus.svg?react';
|
||||
|
||||
export default function TeacherHomePage() {
|
||||
const { data: myLectures } = useMyLectures();
|
||||
const onGoingClasses = myLectures?.data ?? [];
|
||||
console.log(onGoingClasses);
|
||||
// TODO: 새 강의 만들기 스타일 추가, 추가 기능 필요시 추가
|
||||
|
||||
return (
|
||||
<MaxWidthLayout>
|
||||
<ClassGrid title="내 강의">
|
||||
{onGoingClasses.map?.((lecture) => (
|
||||
{onGoingClasses.map((lecture) => (
|
||||
<ClassCard
|
||||
key={lecture.id}
|
||||
path={`/lecture/${lecture.id}`}
|
||||
@ -20,7 +22,13 @@ export default function TeacherHomePage() {
|
||||
{lecture.title}
|
||||
</ClassCard>
|
||||
))}
|
||||
<ClassCard path={'/lecture/create'}>새 강의 만들기</ClassCard>
|
||||
<Link
|
||||
to={'/lecture/create'}
|
||||
className={styles.add}
|
||||
>
|
||||
<PlusIcon />
|
||||
<span>새 강의 만들기</span>
|
||||
</Link>
|
||||
</ClassGrid>
|
||||
</MaxWidthLayout>
|
||||
);
|
||||
|
@ -0,0 +1,21 @@
|
||||
.add {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
margin-bottom: 32px;
|
||||
background-color: var(--background);
|
||||
color: var(--text-color);
|
||||
stroke: var(--text-color);
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.4;
|
||||
border-radius: 20px;
|
||||
transition: background-color 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--background-secondary);
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ import { userTypeSlice } from './userTypeSlice';
|
||||
import { tokenSlice } from './tokenSlice';
|
||||
import { userNameSlice } from './userNameSlice';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import { liveSlice } from './liveSlice';
|
||||
|
||||
const useBoundStore = create(
|
||||
persist(
|
||||
@ -11,7 +10,6 @@ const useBoundStore = create(
|
||||
...userTypeSlice(...a),
|
||||
...tokenSlice(...a),
|
||||
...userNameSlice(...a),
|
||||
...liveSlice(...a),
|
||||
}),
|
||||
{ name: 'bound-store' }
|
||||
)
|
||||
|
@ -1,6 +0,0 @@
|
||||
export const liveSlice = (set) => ({
|
||||
liveToken: null,
|
||||
setLiveToken: (liveToken) => set({ liveToken }),
|
||||
participants: 0,
|
||||
setParticipants: (participants) => set({ participants }),
|
||||
});
|
Loading…
Reference in New Issue
Block a user