미사용 요소 제거
This commit is contained in:
32
src/_nav.tsx
32
src/_nav.tsx
@@ -2,7 +2,6 @@ import React from 'react'
|
|||||||
import CIcon from '@coreui/icons-react'
|
import CIcon from '@coreui/icons-react'
|
||||||
import {
|
import {
|
||||||
cilSpeedometer,
|
cilSpeedometer,
|
||||||
cilStar,
|
|
||||||
} from '@coreui/icons'
|
} from '@coreui/icons'
|
||||||
import { CNavGroup, CNavItem, CNavTitle } from '@coreui/react'
|
import { CNavGroup, CNavItem, CNavTitle } from '@coreui/react'
|
||||||
|
|
||||||
@@ -21,37 +20,6 @@ const _nav = [
|
|||||||
component: CNavTitle,
|
component: CNavTitle,
|
||||||
name: 'Menu',
|
name: 'Menu',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
component: CNavTitle,
|
|
||||||
name: 'Extras',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: CNavGroup,
|
|
||||||
name: 'Pages',
|
|
||||||
icon: <CIcon icon={cilStar} customClassName="nav-icon" />,
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
component: CNavItem,
|
|
||||||
name: 'Login',
|
|
||||||
to: '/login',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: CNavItem,
|
|
||||||
name: 'Register',
|
|
||||||
to: '/register',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: CNavItem,
|
|
||||||
name: 'Error 404',
|
|
||||||
to: '/404',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: CNavItem,
|
|
||||||
name: 'Error 500',
|
|
||||||
to: '/500',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
export default _nav
|
export default _nav
|
||||||
|
|||||||
BIN
src/assets/images/avatars/default.png
Normal file
BIN
src/assets/images/avatars/default.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
@@ -5,14 +5,7 @@ const AppFooter = () => {
|
|||||||
return (
|
return (
|
||||||
<CFooter className="px-4">
|
<CFooter className="px-4">
|
||||||
<div>
|
<div>
|
||||||
<a href="https://coreui.io" target="_blank" rel="noopener noreferrer">
|
<span className="m-2">CoreUI React Referrence :</span>
|
||||||
CoreUI
|
|
||||||
</a>
|
|
||||||
<span className="ms-1">© 2025 creativeLabs.</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<span className="m-2">Referrence :</span>
|
|
||||||
<a href="https://coreui.io/demos/react/5.5/free/?theme=light#/dashboard" target="_blank" rel="noopener noreferrer">
|
<a href="https://coreui.io/demos/react/5.5/free/?theme=light#/dashboard" target="_blank" rel="noopener noreferrer">
|
||||||
Demo
|
Demo
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -69,17 +69,6 @@ const AppHeader = () => {
|
|||||||
{member.memberId}
|
{member.memberId}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<CIcon icon={cilBell} size="lg" />
|
|
||||||
</CNavLink>
|
|
||||||
</CNavItem>
|
|
||||||
<CNavItem>
|
|
||||||
<CNavLink href="#">
|
|
||||||
<CIcon icon={cilList} size="lg" />
|
|
||||||
</CNavLink>
|
|
||||||
</CNavItem>
|
|
||||||
<CNavItem>
|
|
||||||
<CNavLink href="#">
|
|
||||||
<CIcon icon={cilEnvelopeOpen} size="lg" />
|
|
||||||
</CNavLink>
|
</CNavLink>
|
||||||
</CNavItem>
|
</CNavItem>
|
||||||
</CHeaderNav>
|
</CHeaderNav>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import React from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import {
|
import {
|
||||||
CAvatar,
|
CAvatar,
|
||||||
CBadge,
|
|
||||||
CDropdown,
|
CDropdown,
|
||||||
CDropdownDivider,
|
CDropdownDivider,
|
||||||
CDropdownHeader,
|
CDropdownHeader,
|
||||||
@@ -10,24 +9,64 @@ import {
|
|||||||
CDropdownToggle,
|
CDropdownToggle,
|
||||||
} from '@coreui/react'
|
} from '@coreui/react'
|
||||||
import {
|
import {
|
||||||
cilBell,
|
|
||||||
cilCreditCard,
|
|
||||||
cilCommentSquare,
|
|
||||||
cilEnvelopeOpen,
|
|
||||||
cilFile,
|
|
||||||
cilLockLocked,
|
|
||||||
cilSettings,
|
|
||||||
cilTask,
|
|
||||||
cilUser,
|
cilUser,
|
||||||
cilAccountLogout,
|
cilAccountLogout,
|
||||||
|
cilClock,
|
||||||
} from '@coreui/icons'
|
} from '@coreui/icons'
|
||||||
import { useAuth } from 'src/hooks/useAuth'
|
import { useAuth } from 'src/hooks/useAuth'
|
||||||
|
import { getAccessTokenFromCookie, getRefreshTokenFromCookie, getUserFromToken } from 'src/axios/authService'
|
||||||
import CIcon from '@coreui/icons-react'
|
import CIcon from '@coreui/icons-react'
|
||||||
|
|
||||||
import avatar8 from 'src/assets/images/avatars/8.jpg'
|
import avatar8 from 'src/assets/images/avatars/default.png'
|
||||||
|
|
||||||
const AppHeaderDropdown = () => {
|
const AppHeaderDropdown = () => {
|
||||||
const { logout } = useAuth()
|
const { logout, state } = useAuth()
|
||||||
|
const [accessTokenExpiry, setAccessTokenExpiry] = useState<string>('')
|
||||||
|
const [refreshTokenExpiry, setRefreshTokenExpiry] = useState<string>('')
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const formatExpiry = (diff: number): string => {
|
||||||
|
if (diff <= 0) return '만료됨'
|
||||||
|
const days = Math.floor(diff / (24 * 60 * 60 * 1000))
|
||||||
|
const hours = Math.floor((diff % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000))
|
||||||
|
const minutes = Math.floor((diff % (60 * 60 * 1000)) / 60000)
|
||||||
|
const seconds = Math.floor((diff % 60000) / 1000)
|
||||||
|
|
||||||
|
if (days > 0) return `${days}일 ${hours}시간 후 만료`
|
||||||
|
if (hours > 0) return `${hours}시간 ${minutes}분 후 만료`
|
||||||
|
return `${minutes}분 ${seconds}초 후 만료`
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateExpiry = () => {
|
||||||
|
const now = new Date()
|
||||||
|
|
||||||
|
// Access Token
|
||||||
|
const accessToken = getAccessTokenFromCookie() || localStorage.getItem('accessToken')
|
||||||
|
if (accessToken) {
|
||||||
|
const decoded = getUserFromToken(accessToken)
|
||||||
|
if (decoded?.exp) {
|
||||||
|
const diff = decoded.exp * 1000 - now.getTime()
|
||||||
|
setAccessTokenExpiry(formatExpiry(diff))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refresh Token
|
||||||
|
const refreshToken = getRefreshTokenFromCookie() || localStorage.getItem('refreshToken')
|
||||||
|
if (refreshToken) {
|
||||||
|
const decoded = getUserFromToken(refreshToken)
|
||||||
|
if (decoded?.exp) {
|
||||||
|
const diff = decoded.exp * 1000 - now.getTime()
|
||||||
|
setRefreshTokenExpiry(formatExpiry(diff))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setRefreshTokenExpiry('HttpOnly (접근 불가)')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateExpiry()
|
||||||
|
const interval = setInterval(updateExpiry, 1000)
|
||||||
|
return () => clearInterval(interval)
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CDropdown variant="nav-item">
|
<CDropdown variant="nav-item">
|
||||||
@@ -36,56 +75,21 @@ const AppHeaderDropdown = () => {
|
|||||||
</CDropdownToggle>
|
</CDropdownToggle>
|
||||||
<CDropdownMenu className="pt-0">
|
<CDropdownMenu className="pt-0">
|
||||||
<CDropdownHeader className="bg-body-secondary fw-semibold mb-2">Account</CDropdownHeader>
|
<CDropdownHeader className="bg-body-secondary fw-semibold mb-2">Account</CDropdownHeader>
|
||||||
<CDropdownItem href="#">
|
<CDropdownItem className="disabled">
|
||||||
<CIcon icon={cilBell} className="me-2" />
|
|
||||||
Updates
|
|
||||||
<CBadge color="info" className="ms-2">
|
|
||||||
42
|
|
||||||
</CBadge>
|
|
||||||
</CDropdownItem>
|
|
||||||
<CDropdownItem href="#">
|
|
||||||
<CIcon icon={cilEnvelopeOpen} className="me-2" />
|
|
||||||
Messages
|
|
||||||
<CBadge color="success" className="ms-2">
|
|
||||||
42
|
|
||||||
</CBadge>
|
|
||||||
</CDropdownItem>
|
|
||||||
<CDropdownItem href="#">
|
|
||||||
<CIcon icon={cilTask} className="me-2" />
|
|
||||||
Tasks
|
|
||||||
<CBadge color="danger" className="ms-2">
|
|
||||||
42
|
|
||||||
</CBadge>
|
|
||||||
</CDropdownItem>
|
|
||||||
<CDropdownItem href="#">
|
|
||||||
<CIcon icon={cilCommentSquare} className="me-2" />
|
|
||||||
Comments
|
|
||||||
<CBadge color="warning" className="ms-2">
|
|
||||||
42
|
|
||||||
</CBadge>
|
|
||||||
</CDropdownItem>
|
|
||||||
<CDropdownHeader className="bg-body-secondary fw-semibold my-2">Settings</CDropdownHeader>
|
|
||||||
<CDropdownItem href="#">
|
|
||||||
<CIcon icon={cilUser} className="me-2" />
|
<CIcon icon={cilUser} className="me-2" />
|
||||||
Profile
|
ID: {state.member?.memberId || '-'}
|
||||||
</CDropdownItem>
|
</CDropdownItem>
|
||||||
<CDropdownItem href="#">
|
<CDropdownItem className="disabled">
|
||||||
<CIcon icon={cilSettings} className="me-2" />
|
<CIcon icon={cilUser} className="me-2" />
|
||||||
Settings
|
이름: {state.member?.memberName || '-'}
|
||||||
</CDropdownItem>
|
</CDropdownItem>
|
||||||
<CDropdownItem href="#">
|
<CDropdownItem className="disabled">
|
||||||
<CIcon icon={cilCreditCard} className="me-2" />
|
<CIcon icon={cilClock} className="me-2" />
|
||||||
Payments
|
Access: {accessTokenExpiry}
|
||||||
<CBadge color="secondary" className="ms-2">
|
|
||||||
42
|
|
||||||
</CBadge>
|
|
||||||
</CDropdownItem>
|
</CDropdownItem>
|
||||||
<CDropdownItem href="#">
|
<CDropdownItem className="disabled">
|
||||||
<CIcon icon={cilFile} className="me-2" />
|
<CIcon icon={cilClock} className="me-2" />
|
||||||
Projects
|
Refresh: {refreshTokenExpiry}
|
||||||
<CBadge color="primary" className="ms-2">
|
|
||||||
42
|
|
||||||
</CBadge>
|
|
||||||
</CDropdownItem>
|
</CDropdownItem>
|
||||||
<CDropdownDivider />
|
<CDropdownDivider />
|
||||||
<CDropdownItem onClick={logout} style={{ cursor: 'pointer' }}>
|
<CDropdownItem onClick={logout} style={{ cursor: 'pointer' }}>
|
||||||
|
|||||||
@@ -1,210 +1,10 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import classNames from 'classnames'
|
|
||||||
|
|
||||||
import {
|
|
||||||
CAvatar,
|
|
||||||
CButton,
|
|
||||||
CButtonGroup,
|
|
||||||
CCard,
|
|
||||||
CCardBody,
|
|
||||||
CCardFooter,
|
|
||||||
CCardHeader,
|
|
||||||
CCol,
|
|
||||||
CProgress,
|
|
||||||
CRow,
|
|
||||||
CTable,
|
|
||||||
CTableBody,
|
|
||||||
CTableDataCell,
|
|
||||||
CTableHead,
|
|
||||||
CTableHeaderCell,
|
|
||||||
CTableRow,
|
|
||||||
} from '@coreui/react'
|
|
||||||
import CIcon from '@coreui/icons-react'
|
|
||||||
import {
|
|
||||||
cibCcAmex,
|
|
||||||
cibCcApplePay,
|
|
||||||
cibCcMastercard,
|
|
||||||
cibCcPaypal,
|
|
||||||
cibCcStripe,
|
|
||||||
cibCcVisa,
|
|
||||||
cibGoogle,
|
|
||||||
cibFacebook,
|
|
||||||
cibLinkedin,
|
|
||||||
cifBr,
|
|
||||||
cifEs,
|
|
||||||
cifFr,
|
|
||||||
cifIn,
|
|
||||||
cifPl,
|
|
||||||
cifUs,
|
|
||||||
cibTwitter,
|
|
||||||
cilCloudDownload,
|
|
||||||
cilPeople,
|
|
||||||
cilUser,
|
|
||||||
cilUserFemale,
|
|
||||||
} from '@coreui/icons'
|
|
||||||
|
|
||||||
import avatar1 from 'src/assets/images/avatars/1.jpg'
|
|
||||||
import avatar2 from 'src/assets/images/avatars/2.jpg'
|
|
||||||
import avatar3 from 'src/assets/images/avatars/3.jpg'
|
|
||||||
import avatar4 from 'src/assets/images/avatars/4.jpg'
|
|
||||||
import avatar5 from 'src/assets/images/avatars/5.jpg'
|
|
||||||
import avatar6 from 'src/assets/images/avatars/6.jpg'
|
|
||||||
|
|
||||||
import MainChart from 'src/views/dashboard/MainChart'
|
|
||||||
|
|
||||||
const Dashboard = () => {
|
const Dashboard = () => {
|
||||||
const tableExample = [
|
|
||||||
{
|
|
||||||
avatar: { src: avatar1, status: 'success' },
|
|
||||||
user: {
|
|
||||||
name: 'Yiorgos Avraamu',
|
|
||||||
new: true,
|
|
||||||
registered: 'Jan 1, 2023',
|
|
||||||
},
|
|
||||||
country: { name: 'USA', flag: cifUs },
|
|
||||||
usage: {
|
|
||||||
value: 50,
|
|
||||||
period: 'Jun 11, 2023 - Jul 10, 2023',
|
|
||||||
color: 'success',
|
|
||||||
},
|
|
||||||
payment: { name: 'Mastercard', icon: cibCcMastercard },
|
|
||||||
activity: '10 sec ago',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
avatar: { src: avatar2, status: 'danger' },
|
|
||||||
user: {
|
|
||||||
name: 'Avram Tarasios',
|
|
||||||
new: false,
|
|
||||||
registered: 'Jan 1, 2023',
|
|
||||||
},
|
|
||||||
country: { name: 'Brazil', flag: cifBr },
|
|
||||||
usage: {
|
|
||||||
value: 22,
|
|
||||||
period: 'Jun 11, 2023 - Jul 10, 2023',
|
|
||||||
color: 'info',
|
|
||||||
},
|
|
||||||
payment: { name: 'Visa', icon: cibCcVisa },
|
|
||||||
activity: '5 minutes ago',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
avatar: { src: avatar3, status: 'warning' },
|
|
||||||
user: { name: 'Quintin Ed', new: true, registered: 'Jan 1, 2023' },
|
|
||||||
country: { name: 'India', flag: cifIn },
|
|
||||||
usage: {
|
|
||||||
value: 74,
|
|
||||||
period: 'Jun 11, 2023 - Jul 10, 2023',
|
|
||||||
color: 'warning',
|
|
||||||
},
|
|
||||||
payment: { name: 'Stripe', icon: cibCcStripe },
|
|
||||||
activity: '1 hour ago',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
avatar: { src: avatar4, status: 'secondary' },
|
|
||||||
user: { name: 'Enéas Kwadwo', new: true, registered: 'Jan 1, 2023' },
|
|
||||||
country: { name: 'France', flag: cifFr },
|
|
||||||
usage: {
|
|
||||||
value: 98,
|
|
||||||
period: 'Jun 11, 2023 - Jul 10, 2023',
|
|
||||||
color: 'danger',
|
|
||||||
},
|
|
||||||
payment: { name: 'PayPal', icon: cibCcPaypal },
|
|
||||||
activity: 'Last month',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
avatar: { src: avatar5, status: 'success' },
|
|
||||||
user: {
|
|
||||||
name: 'Agapetus Tadeáš',
|
|
||||||
new: true,
|
|
||||||
registered: 'Jan 1, 2023',
|
|
||||||
},
|
|
||||||
country: { name: 'Spain', flag: cifEs },
|
|
||||||
usage: {
|
|
||||||
value: 22,
|
|
||||||
period: 'Jun 11, 2023 - Jul 10, 2023',
|
|
||||||
color: 'primary',
|
|
||||||
},
|
|
||||||
payment: { name: 'Google Wallet', icon: cibCcApplePay },
|
|
||||||
activity: 'Last week',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
avatar: { src: avatar6, status: 'danger' },
|
|
||||||
user: {
|
|
||||||
name: 'Friderik Dávid',
|
|
||||||
new: true,
|
|
||||||
registered: 'Jan 1, 2023',
|
|
||||||
},
|
|
||||||
country: { name: 'Poland', flag: cifPl },
|
|
||||||
usage: {
|
|
||||||
value: 43,
|
|
||||||
period: 'Jun 11, 2023 - Jul 10, 2023',
|
|
||||||
color: 'success',
|
|
||||||
},
|
|
||||||
payment: { name: 'Amex', icon: cibCcAmex },
|
|
||||||
activity: 'Last week',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="d-flex justify-content-center align-items-center" style={{ minHeight: '60vh' }}>
|
||||||
<CCard className="mb-4">
|
<h1 className="text-body-secondary">Welcome to Admin Sample</h1>
|
||||||
<CCardHeader>Traffic {' & '} Sales</CCardHeader>
|
</div>
|
||||||
<CCardBody>
|
|
||||||
<CTable align="middle" className="mb-0 border" hover responsive>
|
|
||||||
<CTableHead className="text-nowrap">
|
|
||||||
<CTableRow>
|
|
||||||
<CTableHeaderCell className="bg-body-tertiary text-center">
|
|
||||||
<CIcon icon={cilPeople} />
|
|
||||||
</CTableHeaderCell>
|
|
||||||
<CTableHeaderCell className="bg-body-tertiary">User</CTableHeaderCell>
|
|
||||||
<CTableHeaderCell className="bg-body-tertiary text-center">
|
|
||||||
Country
|
|
||||||
</CTableHeaderCell>
|
|
||||||
<CTableHeaderCell className="bg-body-tertiary">Usage</CTableHeaderCell>
|
|
||||||
<CTableHeaderCell className="bg-body-tertiary text-center">
|
|
||||||
Payment Method
|
|
||||||
</CTableHeaderCell>
|
|
||||||
<CTableHeaderCell className="bg-body-tertiary">Activity</CTableHeaderCell>
|
|
||||||
</CTableRow>
|
|
||||||
</CTableHead>
|
|
||||||
<CTableBody>
|
|
||||||
{tableExample.map((item, index) => (
|
|
||||||
<CTableRow v-for="item in tableItems" key={index}>
|
|
||||||
<CTableDataCell className="text-center">
|
|
||||||
<CAvatar size="md" src={item.avatar.src} status={item.avatar.status} />
|
|
||||||
</CTableDataCell>
|
|
||||||
<CTableDataCell>
|
|
||||||
<div>{item.user.name}</div>
|
|
||||||
<div className="small text-body-secondary text-nowrap">
|
|
||||||
<span>{item.user.new ? 'New' : 'Recurring'}</span> | Registered:{' '}
|
|
||||||
{item.user.registered}
|
|
||||||
</div>
|
|
||||||
</CTableDataCell>
|
|
||||||
<CTableDataCell className="text-center">
|
|
||||||
<CIcon size="xl" icon={item.country.flag} title={item.country.name} />
|
|
||||||
</CTableDataCell>
|
|
||||||
<CTableDataCell>
|
|
||||||
<div className="d-flex justify-content-between text-nowrap">
|
|
||||||
<div className="fw-semibold">{item.usage.value}%</div>
|
|
||||||
<div className="ms-3">
|
|
||||||
<small className="text-body-secondary">{item.usage.period}</small>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<CProgress thin color={item.usage.color} value={item.usage.value} />
|
|
||||||
</CTableDataCell>
|
|
||||||
<CTableDataCell className="text-center">
|
|
||||||
<CIcon size="xl" icon={item.payment.icon} />
|
|
||||||
</CTableDataCell>
|
|
||||||
<CTableDataCell>
|
|
||||||
<div className="small text-body-secondary text-nowrap">Last login</div>
|
|
||||||
<div className="fw-semibold text-nowrap">{item.activity}</div>
|
|
||||||
</CTableDataCell>
|
|
||||||
</CTableRow>
|
|
||||||
))}
|
|
||||||
</CTableBody>
|
|
||||||
</CTable>
|
|
||||||
</CCardBody>
|
|
||||||
</CCard>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user