Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ThemeProvider, Global } from '@emotion/react';
import { theme } from '@/shared/theme/theme.styles';
import { globalStyles } from '@/shared/theme/global';
import { RecoilRoot } from 'recoil';
import { BrowserRouter as Router } from 'react-router-dom';
import { BrowserRouter as Router, useLocation, matchPath } from 'react-router-dom';
import { UserContext } from '@/entities/Context/LoginContext';
import { AppRoutes } from '@/app/router/AppRoutes';
import { useAuth } from './hooks/useAccessToken';
Expand All @@ -23,6 +23,7 @@ export default function App() {

function AuthWrapper() {
const { accessToken, refreshToken, user, setAuthInfo, removeAuthInfo, loading } = useAuth();
const location = useLocation();

if (loading) {
return null; // 또는 로딩 스피너를 여기에 렌더링
Expand All @@ -31,10 +32,13 @@ function AuthWrapper() {
let role = user?.role || null;
if (role === 'STUDENT') role = 'STU';
else if (role === 'TEACHER') role = 'TCH';

// Hide Navbar on markdown editor route
const hideNavbar = !!matchPath('/class/:classRoomId/:directoryId/make/lesson/markdown', location.pathname);
return (
<UserContext.Provider value={{ accessToken, refreshToken, user, setAuthInfo, removeAuthInfo }}>
<Navbar userId={Number(user?.userId) || 0} username={user?.username || ''} role={role} />
<UserContext.Provider value={{ accessToken, refreshToken, user, setAuthInfo, removeAuthInfo }}>
{!hideNavbar && (
<Navbar userId={Number(user?.userId) || 0} username={user?.username || ''} role={role} />
)}
<AppRoutes role={role} />
</UserContext.Provider>
);
Expand Down
44 changes: 34 additions & 10 deletions src/entities/Make/MarkDown/MarkDownEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import MDEditor from '@uiw/react-md-editor';
import * as s from './styles';
import { useNavigate } from 'react-router-dom';
import { Modal } from '@/entities/UI/Modal';
import { submitMarkDown } from '../api/useMarkDown';
// 언젠가는 Modal 컴포넌트 다시 손봐야 할듯
const AIAgentView = () => <div style={{ padding: '20px' }}>AI Agent View Placeholder</div>;

export default function MarkDwonEditor({ classRoomId, directoryId }: { classRoomId: string, directoryId: string }) {
const defaultTemplate = '# 마크다운을 작성해보세요\n\n## 제목\n- 목록 1\n- 목록 2\n\n**굵은 글씨**와 *기울임체*도 사용할 수 있습니다.';
Expand All @@ -16,6 +17,17 @@ export default function MarkDwonEditor({ classRoomId, directoryId }: { classRoom
const [isCancelOpen, setIsCancelOpen] = useState(false);
const [isPreviousOpen, setIsPreviousOpen] = useState(false);
const [isEndOpen, setIsEndOpen] = useState(false);
const [viewerMode, setViewerMode] = useState<'preview' | 'aiAgent'>('preview');

useEffect(() => {
// store previous value to restore later
const prev = getComputedStyle(document.body).getPropertyValue('--app-top-offset');
document.body.style.setProperty('--app-top-offset', '0px');
return () => {
if (prev) document.body.style.setProperty('--app-top-offset', prev);
else document.body.style.removeProperty('--app-top-offset');
};
}, []);

const endModal = () => {
setIsEndOpen(true);
Expand Down Expand Up @@ -58,7 +70,7 @@ export default function MarkDwonEditor({ classRoomId, directoryId }: { classRoom
}

return (
<s.Container>
<s.Container className="no-top-offset">
<s.EditorSection>
<s.SectionTitle
placeholder='제목을 입력해주세요'
Expand Down Expand Up @@ -90,13 +102,26 @@ export default function MarkDwonEditor({ classRoomId, directoryId }: { classRoom
</s.EditorSection>

<s.ViewerSection>
<s.SectionTitle placeholder='제목을 입력해주세요' value={title}></s.SectionTitle>
<s.ViewerWrapper data-color-mode="light">
<MDEditor.Markdown
source={mdContent}
style={{ padding: '20px' }}
/>
</s.ViewerWrapper>
<s.ViewerHeader>
<s.ToggleWrapper>
<s.ToggleButton active={viewerMode === 'preview'} onClick={() => setViewerMode('preview')}>
미리보기
</s.ToggleButton>
<s.ToggleButton active={viewerMode === 'aiAgent'} onClick={() => setViewerMode('aiAgent')}>
AI Agent
</s.ToggleButton>
</s.ToggleWrapper>
</s.ViewerHeader>
{viewerMode === 'preview' ? (
<s.ViewerWrapper data-color-mode="light">
<MDEditor.Markdown
source={mdContent}
style={{ padding: '20px' }}
/>
</s.ViewerWrapper>
) : (
<AIAgentView />
)}
</s.ViewerSection>
{/* 취소 */}
{isCancelOpen && (
Expand Down Expand Up @@ -155,4 +180,3 @@ export default function MarkDwonEditor({ classRoomId, directoryId }: { classRoom
</s.Container>
);
}

86 changes: 64 additions & 22 deletions src/entities/Make/MarkDown/styles.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import styled from '@emotion/styled';
import { blue, theme } from '@/shared/theme/theme.styles';
import { fonts } from '@/shared/theme/font.styles';
import styled from "@emotion/styled";
import { blue, theme } from "@/shared/theme/theme.styles";
import { fonts } from "@/shared/theme/font.styles";

export const Container = styled.div`
display: flex;
gap: 20px;
height: 100vh;
padding: 20px;
background-color: ${theme.colors.gray[200]};

@media (max-width: 1200px) {
gap: 16px;
Expand All @@ -20,17 +17,20 @@ export const Container = styled.div`
gap: 12px;
padding: 12px;
}

&.no-top-offset {
--app-top-offset: 0px;
}
`;

export const EditorSection = styled.div`
flex: 1;
display: flex;
flex-direction: column;
background: ${theme.colors.white};
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
height: 95%;
height: 100%;
border-right: 1px solid ${theme.colors.gray[300]};

@media (max-width: 768px) {
height: auto;
Expand All @@ -44,9 +44,8 @@ export const ViewerSection = styled.div`
flex-direction: column;
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
height: 95%;
height: 100%;

@media (max-width: 768px) {
height: auto;
Expand All @@ -56,12 +55,10 @@ export const ViewerSection = styled.div`

export const SectionTitle = styled.input`
margin: 0;
padding: 16px 20px;
background: #f8f9fa;
padding: 24px 20px 16px 20px;
border: none;
outline: none;
border-bottom: 1px solid #e9ecef;
${fonts.P2};
${fonts.P5};
font-weight: 600;
color: #495057;

Expand Down Expand Up @@ -173,23 +170,35 @@ export const ViewerWrapper = styled.div`
overflow-y: auto;
padding: 20px;

h1, h2, h3, h4, h5, h6 {
h1,
h2,
h3,
h4,
h5,
h6 {
margin-top: 24px;
margin-bottom: 16px;
font-weight: 600;
line-height: 1.25;
}

h1 { font-size: 2em; }
h2 { font-size: 1.5em; }
h3 { font-size: 1.25em; }
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.25em;
}

p {
margin-bottom: 16px;
line-height: 1.6;
}

ul, ol {
ul,
ol {
margin-bottom: 16px;
padding-left: 24px;
}
Expand All @@ -202,7 +211,7 @@ export const ViewerWrapper = styled.div`
background-color: #f1f3f4;
padding: 2px 6px;
border-radius: 4px;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
${fonts.P2};
}

Expand All @@ -228,4 +237,37 @@ export const ViewerWrapper = styled.div`
@media (max-width: 768px) {
padding: 12px;
}
`;
`;

export const ViewerHeader = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
padding-bottom: 0;
`;

export const ToggleWrapper = styled.div`
display: flex;
border-bottom: 1px solid ${theme.colors.gray[300]};
`;

export const ToggleButton = styled.button<{ active: boolean }>`
padding: 8px 16px;
border: none;
background-color: transparent;
border-bottom: 2px solid
${({ active }) => (active ? theme.colors.blue[500] : "white")};
color: ${({ active, theme }) =>
active ? theme.colors.black : theme.colors.gray[500]};
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
margin-bottom: -1px;
${fonts.P2};

&:focus {
outline: none;
}
`;
3 changes: 2 additions & 1 deletion src/shared/theme/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ export const globalStyles = css`
margin: 0;
font-family: 'Pretendard', -apple-system, BlinkMacSystemFont, 'Segoe UI',
Roboto, 'Helvetica Neue', Arial, 'Apple SD Gothic Neo', sans-serif;
padding-top: 50px;
/* allow pages to override top offset (e.g., hide navbar) */
padding-top: var(--app-top-offset, 50px);
background-color: ${theme.colors.white};
color: ${theme.colors.black};
height: 100%;
Expand Down
Loading