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
65 changes: 28 additions & 37 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useState } from 'react'
import { Routes, Route, useNavigate } from 'react-router-dom'
import { Box, Typography, Container, Card, CardContent, Grid, Button, Collapse, IconButton } from '@mui/material'
import {
School as EnglishIcon,
Chat as FreetalkIcon,
Mic as SpeakingIcon,
Create as WritingCategoryIcon,
Headphones as OpicIcon,
Edit as WritingIcon,
People as PeopleIcon,
Expand All @@ -20,35 +20,35 @@ function Dashboard() {

const learningModes = [
{
id: 'english',
title: '영어공부',
description: 'OPIC 연습, 작문 연습으로 영어 실력 향상',
icon: EnglishIcon,
id: 'speaking',
title: '말하기연습',
description: '오픽 연습과 AI 대화로 스피킹 실력 향상',
icon: SpeakingIcon,
color: '#2196f3',
children: [
{ id: 'opic', title: 'OPIC 연습', icon: OpicIcon, path: '/opic', description: '레벨별 맞춤 연습' },
{ id: 'writing', title: '작문 연습', icon: WritingIcon, path: '/writing', description: '문법 교정 & 피드백' },
{ id: 'opic', title: '오픽연습', icon: OpicIcon, path: '/opic', description: '레벨별 맞춤 연습' },
{ id: 'ai-talk', title: 'AI와 말해보기', icon: AiIcon, path: '/freetalk/ai', description: 'AI와 자유로운 대화' },
],
},
{
id: 'freetalk',
title: '프리토킹',
description: '사람들과 또는 AI와 자유롭게 대화',
icon: FreetalkIcon,
id: 'writing',
title: '쓰기연습',
description: '채팅과 작문으로 라이팅 실력 향상',
icon: WritingCategoryIcon,
color: '#4caf50',
children: [
{ id: 'freetalk-people', title: '사람들과', icon: PeopleIcon, path: '/freetalk/people', description: '다른 학습자와 대화' },
{ id: 'freetalk-ai', title: 'AI와', icon: AiIcon, path: '/freetalk/ai', description: 'AI와 자유 대화' },
{ id: 'chat-people', title: '사람들과 채팅하기', icon: PeopleIcon, path: '/freetalk/people', description: '다른 학습자와 대화' },
{ id: 'writing-practice', title: '작문연습', icon: WritingIcon, path: '/writing', description: '문법 교정 & 피드백' },
],
},
]

const handleCardClick = (mode) => {
if (mode.children) {
setExpandedCard(expandedCard === mode.id ? null : mode.id)
} else if (mode.path) {
navigate(mode.path)
}
const handleCardHover = (modeId) => {
setExpandedCard(modeId)
}

const handleCardLeave = () => {
setExpandedCard(null)
}

const handleSubItemClick = (path, e) => {
Expand All @@ -67,33 +67,24 @@ function Dashboard() {
</Typography>
</Box>

<Box sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>
<Grid container spacing={3}>
{learningModes.map((mode) => {
const Icon = mode.icon
const isExpanded = expandedCard === mode.id
const hasChildren = mode.children && mode.children.length > 0

return (
<Box
key={mode.id}
sx={{
transition: 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)',
width: isExpanded ? { xs: '100%', md: '500px' } : { xs: '100%', sm: 'calc(50% - 12px)', md: 'calc(33.333% - 16px)' },
minWidth: isExpanded ? { xs: '100%', md: '500px' } : 'auto',
}}
>
<Grid item xs={12} sm={6} key={mode.id}>
<Card
onClick={() => handleCardClick(mode)}
onMouseEnter={() => handleCardHover(mode.id)}
onMouseLeave={handleCardLeave}
sx={{
height: '100%',
cursor: 'pointer',
transition: 'all 0.4s cubic-bezier(0.4, 0, 0.2, 1)',
transform: isExpanded ? 'scale(1.02)' : 'scale(1)',
transition: 'all 0.3s ease',
boxShadow: isExpanded ? 8 : 1,
border: isExpanded ? `2px solid ${mode.color}` : '2px solid transparent',
'&:hover': {
transform: isExpanded ? 'scale(1.02)' : 'translateY(-4px)',
boxShadow: isExpanded ? 8 : 4,
boxShadow: 6,
},
}}
>
Expand Down Expand Up @@ -191,10 +182,10 @@ function Dashboard() {
)}
</CardContent>
</Card>
</Box>
</Grid>
)
})}
</Box>
</Grid>

{/* 최근 학습 */}
<Box sx={{ mt: 6 }}>
Expand Down
44 changes: 22 additions & 22 deletions src/layouts/MainLayout/Sidebar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import {
ChevronRight as ChevronRightIcon,
Dashboard as DashboardIcon,
Headphones as OpicIcon,
Chat as FreetalkIcon,
Edit as WritingIcon,
Assessment as ReportIcon,
Settings as SettingsIcon,
School as EnglishIcon,
Mic as SpeakingIcon,
Create as WritingCategoryIcon,
People as PeopleIcon,
SmartToy as AiIcon,
ExpandMore as ExpandMoreIcon,
Expand All @@ -39,44 +39,44 @@ const menuItems = [
category: '학습 모드',
items: [
{
id: 'english',
label: '영어공부',
icon: EnglishIcon,
id: 'speaking',
label: '말하기연습',
icon: SpeakingIcon,
children: [
{
id: 'opic',
label: 'OPIC 연습',
label: '오픽연습',
icon: OpicIcon,
path: '/opic',
description: '레벨별 맞춤 연습'
},
{
id: 'writing',
label: '작문 연습',
icon: WritingIcon,
path: '/writing',
description: '문법 교정 & 피드백'
id: 'ai-talk',
label: 'AI와 말해보기',
icon: AiIcon,
path: '/freetalk/ai',
description: 'AI와 자유로운 대화'
},
],
},
{
id: 'freetalk',
label: '프리토킹',
icon: FreetalkIcon,
id: 'writing',
label: '쓰기연습',
icon: WritingCategoryIcon,
children: [
{
id: 'freetalk-people',
label: '사람들과',
id: 'chat-people',
label: '사람들과 채팅하기',
icon: PeopleIcon,
path: '/freetalk/people',
description: '다른 학습자와 대화'
},
{
id: 'freetalk-ai',
label: 'AI와',
icon: AiIcon,
path: '/freetalk/ai',
description: 'AI와 자유로운 대화'
id: 'writing-practice',
label: '작문연습',
icon: WritingIcon,
path: '/writing',
description: '문법 교정 & 피드백'
},
],
},
Expand Down Expand Up @@ -119,7 +119,7 @@ const Sidebar = ({ open, collapsed, onToggleCollapse, onClose }) => {
// 펼침 상태 (localStorage 저장)
const [expandedMenus, setExpandedMenus] = useState(() => {
const saved = localStorage.getItem('expandedMenus')
return saved ? JSON.parse(saved) : { english: true, freetalk: true }
return saved ? JSON.parse(saved) : { speaking: true, writing: true }
})

useEffect(() => {
Expand Down