fix: dashboard
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="12" cy="12" r="11.625" stroke="#EEEEEE" stroke-width="0.75"/>
|
||||||
|
<g clip-path="url(#clip0_1_21196)">
|
||||||
|
<path d="M15.375 15.375L8.625 8.625" stroke="#B2B2B2" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M14.1094 8.625H8.625V14.1094" stroke="#B2B2B2" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_1_21196">
|
||||||
|
<rect width="13.5" height="13.5" fill="white" transform="translate(5.25 5.25)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 604 B |
@@ -0,0 +1,11 @@
|
|||||||
|
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_1_21191)">
|
||||||
|
<path d="M6.5 11.375C9.19239 11.375 11.375 9.19239 11.375 6.5C11.375 3.80761 9.19239 1.625 6.5 1.625C3.80761 1.625 1.625 3.80761 1.625 6.5C1.625 9.19239 3.80761 11.375 6.5 11.375Z" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M6.5 3.65625V6.5H9.34375" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_1_21191">
|
||||||
|
<rect width="12.75" height="12.75" fill="white" transform="scale(1.01961)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 666 B |
@@ -0,0 +1,10 @@
|
|||||||
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_1_21269)">
|
||||||
|
<path d="M5.625 3.1154V16.8841C5.62704 16.994 5.65802 17.1014 5.7148 17.1955C5.77158 17.2896 5.85217 17.367 5.94843 17.42C6.0447 17.473 6.15323 17.4997 6.2631 17.4974C6.37297 17.4951 6.48028 17.4638 6.57422 17.4068L17.8305 10.5224C17.9204 10.468 17.9947 10.3913 18.0463 10.2998C18.0979 10.2082 18.1251 10.1049 18.1251 9.99977C18.1251 9.89467 18.0979 9.79135 18.0463 9.69979C17.9947 9.60823 17.9204 9.53154 17.8305 9.47711L6.57422 2.59274C6.48028 2.53571 6.37297 2.50447 6.2631 2.50214C6.15323 2.49982 6.0447 2.52651 5.94843 2.57951C5.85217 2.63252 5.77158 2.70996 5.7148 2.80405C5.65802 2.89813 5.62704 3.00552 5.625 3.1154Z" stroke="#848484" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_1_21269">
|
||||||
|
<rect width="19.5" height="19.5" fill="white" transform="scale(1.02564)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 988 B |
@@ -0,0 +1,11 @@
|
|||||||
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_1_21319)">
|
||||||
|
<path d="M11.8125 2.625H2.1875C1.94588 2.625 1.75 2.82088 1.75 3.0625V10.9375C1.75 11.1791 1.94588 11.375 2.1875 11.375H11.8125C12.0541 11.375 12.25 11.1791 12.25 10.9375V3.0625C12.25 2.82088 12.0541 2.625 11.8125 2.625Z" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M9.1875 4.8125C9.1875 5.39266 8.95703 5.94906 8.5468 6.3593C8.13656 6.76953 7.58016 7 7 7C6.41984 7 5.86344 6.76953 5.4532 6.3593C5.04297 5.94906 4.8125 5.39266 4.8125 4.8125" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_1_21319">
|
||||||
|
<rect width="13.5" height="13.5" fill="white" transform="scale(1.03704)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 855 B |
@@ -0,0 +1,13 @@
|
|||||||
|
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_1_21209)">
|
||||||
|
<path d="M5.48438 8.53125C7.16712 8.53125 8.53125 7.16712 8.53125 5.48438C8.53125 3.80163 7.16712 2.4375 5.48438 2.4375C3.80163 2.4375 2.4375 3.80163 2.4375 5.48438C2.4375 7.16712 3.80163 8.53125 5.48438 8.53125Z" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M1.21875 10.5625C2.2623 9.3209 3.73547 8.53125 5.48438 8.53125C7.23328 8.53125 8.70645 9.3209 9.75 10.5625" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M10.1562 3.49096C10.4243 4.12144 10.5625 4.79952 10.5625 5.48463C10.5625 6.16975 10.4243 6.84782 10.1562 7.47831" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M11.6468 2.84375C12.0033 3.67846 12.1871 4.57672 12.1871 5.48438C12.1871 6.39203 12.0033 7.29029 11.6468 8.125" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_1_21209">
|
||||||
|
<rect width="12.75" height="12.75" fill="white" transform="scale(1.01961)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,12 @@
|
|||||||
|
<svg width="13" height="13" viewBox="0 0 13 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_1_21228)">
|
||||||
|
<path d="M8.125 5.6875L5.6875 4.0625V7.3125L8.125 5.6875Z" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M10.9688 2.4375H2.03125C1.80688 2.4375 1.625 2.61938 1.625 2.84375V8.53125C1.625 8.75562 1.80688 8.9375 2.03125 8.9375H10.9688C11.1931 8.9375 11.375 8.75562 11.375 8.53125V2.84375C11.375 2.61938 11.1931 2.4375 10.9688 2.4375Z" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
<path d="M1.625 10.5625H11.375" stroke="#B8B8B8" stroke-width="0.75" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_1_21228">
|
||||||
|
<rect width="12.75" height="12.75" fill="white" transform="scale(1.01961)"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 863 B |
Vendored
+6
@@ -8,6 +8,7 @@ export type IconName =
|
|||||||
| 'bell'
|
| 'bell'
|
||||||
| 'book'
|
| 'book'
|
||||||
| 'calendar'
|
| 'calendar'
|
||||||
|
| 'card-corner-arrow'
|
||||||
| 'caret-down'
|
| 'caret-down'
|
||||||
| 'caret-left'
|
| 'caret-left'
|
||||||
| 'caret-right'
|
| 'caret-right'
|
||||||
@@ -15,6 +16,7 @@ export type IconName =
|
|||||||
| 'chat-centered-dots'
|
| 'chat-centered-dots'
|
||||||
| 'check'
|
| 'check'
|
||||||
| 'check-square'
|
| 'check-square'
|
||||||
|
| 'clock'
|
||||||
| 'close'
|
| 'close'
|
||||||
| 'copy'
|
| 'copy'
|
||||||
| 'eye'
|
| 'eye'
|
||||||
@@ -33,16 +35,20 @@ export type IconName =
|
|||||||
| 'paper-plane-right'
|
| 'paper-plane-right'
|
||||||
| 'pencil'
|
| 'pencil'
|
||||||
| 'phone'
|
| 'phone'
|
||||||
|
| 'play'
|
||||||
| 'plus'
|
| 'plus'
|
||||||
| 'scroll'
|
| 'scroll'
|
||||||
|
| 'shopping-bag'
|
||||||
| 'spinner'
|
| 'spinner'
|
||||||
| 'square'
|
| 'square'
|
||||||
| 'telegram'
|
| 'telegram'
|
||||||
| 'trash'
|
| 'trash'
|
||||||
| 'upload'
|
| 'upload'
|
||||||
| 'user'
|
| 'user'
|
||||||
|
| 'user-sound'
|
||||||
| 'users'
|
| 'users'
|
||||||
| 'users-three'
|
| 'users-three'
|
||||||
|
| 'video'
|
||||||
| 'warning'
|
| 'warning'
|
||||||
|
|
||||||
export const iconNames: readonly IconName[]
|
export const iconNames: readonly IconName[]
|
||||||
|
|||||||
@@ -1,69 +1,226 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="student-dashboard">
|
<div class="dashboard">
|
||||||
<div class="student-dashboard__welcome">
|
<div class="dashboard__main">
|
||||||
<img :src="flower" alt="flower" class="student-dashboard__flower" />
|
<!-- گزارش عملکرد -->
|
||||||
<div>
|
<section class="dashboard__section">
|
||||||
<p class="student-dashboard__hi">سلام بر شما</p>
|
<BoxedIconTitleBlock title="گزارش عملکرد" desc="مروری بر شاخصهای آموزشی و فعالیتهای شما.">
|
||||||
<p class="student-dashboard__greeting">به سامانه موسسه بانو خوش آمدید.</p>
|
<template #icon>
|
||||||
|
<SvgIcon name="heart" :size="24" color="var(--color-primary)" />
|
||||||
|
</template>
|
||||||
|
</BoxedIconTitleBlock>
|
||||||
|
|
||||||
|
<div class="dashboard__stats">
|
||||||
|
<DashboardStatCard
|
||||||
|
v-for="(stat, i) in performanceStats"
|
||||||
|
:key="i"
|
||||||
|
:icon="stat.icon"
|
||||||
|
:label="stat.label"
|
||||||
|
:value="stat.value"
|
||||||
|
:unit="stat.unit"
|
||||||
|
:subtitle="stat.subtitle"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- فعالیت های اخیر -->
|
||||||
|
<section class="dashboard__section">
|
||||||
|
<BoxedIconTitleBlock
|
||||||
|
title="فعالیت های اخیر"
|
||||||
|
desc="گزارشی از جدیدترین خریدها و دورههای تکمیلشده"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<SvgIcon name="heart" :size="24" color="var(--color-primary)" />
|
||||||
|
</template>
|
||||||
|
</BoxedIconTitleBlock>
|
||||||
|
|
||||||
|
<div class="dashboard__activities">
|
||||||
|
<div v-for="(act, i) in activities" :key="i" class="dashboard__activity">
|
||||||
|
<div class="dashboard__pill">
|
||||||
|
<SvgIcon :name="act.pillIcon" :size="'1.125rem'" class="dashboard__pill-icon" />
|
||||||
|
<span class="dashboard__pill-label">{{ act.pillLabel }}</span>
|
||||||
|
</div>
|
||||||
|
<DashboardActivityCard :title="act.title" :meta="act.meta" :meta-icon="act.metaIcon" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="student-dashboard__placeholder">این بخش در مراحل بعدی توسعه مییابد.</p>
|
<aside class="dashboard__aside">
|
||||||
|
<DashboardProfileCard
|
||||||
|
:name="profile.name"
|
||||||
|
:location="profile.location"
|
||||||
|
:stats="profile.stats"
|
||||||
|
/>
|
||||||
|
<DashboardCalendar :month-label="calendar.month" :days="calendar.days" />
|
||||||
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { gallery } from '@/utils/gallery'
|
import SvgIcon from '@/components/icons/SvgIcon.vue'
|
||||||
|
import BoxedIconTitleBlock from '@/components/blocks/BoxedIconTitleBlock.vue'
|
||||||
|
import DashboardStatCard from '@/features/student/pages/components/DashboardStatCard.vue'
|
||||||
|
import DashboardCalendar from '@/features/student/pages/components/DashboardCalendar.vue'
|
||||||
|
import DashboardProfileCard from '@/features/student/pages/components/DashboardProfileCard.vue'
|
||||||
|
import DashboardActivityCard from '@/features/student/pages/components/DashboardActivityCard.vue'
|
||||||
|
|
||||||
const flower = gallery.registrationCompleteFlower
|
const performanceStats = [
|
||||||
|
{
|
||||||
|
icon: 'clock',
|
||||||
|
label: 'ساعات آموزشی سپریشده',
|
||||||
|
value: '۲۵',
|
||||||
|
unit: 'ساعت',
|
||||||
|
subtitle: 'گذرانده شده',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'video',
|
||||||
|
label: 'دوره های خریداری شده',
|
||||||
|
value: '۶',
|
||||||
|
unit: 'دوره',
|
||||||
|
subtitle: 'خریداری شده',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'user-sound',
|
||||||
|
label: 'تعداد جلسات اعزام شده',
|
||||||
|
value: '۱۲',
|
||||||
|
unit: 'جلسه',
|
||||||
|
subtitle: 'اعزام شده است',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const activities = [
|
||||||
|
{
|
||||||
|
pillIcon: 'shopping-bag',
|
||||||
|
pillLabel: 'آخرین دوره خریداری شده',
|
||||||
|
title: 'دوره تاریخچه ایران قدیم',
|
||||||
|
metaIcon: 'calendar',
|
||||||
|
meta: [
|
||||||
|
{ label: 'تاریخ شروع:', value: '۱۴۰۰/۷/۱۹, ۸:۳۰', numeric: true },
|
||||||
|
{ label: 'استاد:', value: 'علیرضا حسنی' },
|
||||||
|
{ label: 'تاریخ پایان:', value: '۱۴۰۰/۱۱/۱۰, ۸:۳۰', numeric: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pillIcon: 'video',
|
||||||
|
pillLabel: 'اخرین جلسه دیده شده',
|
||||||
|
title: 'دوره تخصصی تربیت مبلغ بین الملل',
|
||||||
|
metaIcon: 'video',
|
||||||
|
meta: [
|
||||||
|
{ label: 'جلسه:', value: 'بیستم و دوم' },
|
||||||
|
{ label: 'استاد:', value: 'علیرضا حسنی' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const profile = {
|
||||||
|
name: 'سید احمد علیزاده',
|
||||||
|
location: 'قم، ایران',
|
||||||
|
stats: [
|
||||||
|
{ label: 'مدت عضویت', value: '۲۳', unit: 'روز' },
|
||||||
|
{ label: 'دورههای تکمیلشده', value: '۱۲', unit: 'عدد' },
|
||||||
|
{ label: 'دورههای فعال', value: '۵', unit: 'عدد' },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
const calendar = {
|
||||||
|
month: 'شهریور ماه',
|
||||||
|
days: [
|
||||||
|
{ weekday: 'شنبه', day: '۱۵' },
|
||||||
|
{ weekday: 'یکشنبه', day: '۱۴' },
|
||||||
|
{ weekday: 'دوشنبه', day: '۱۳', marker: true },
|
||||||
|
{ weekday: 'سه شنبه', day: '۱۲' },
|
||||||
|
{ weekday: 'چهارشنبه', day: '۱۱', selected: true },
|
||||||
|
{ weekday: 'پنجشنبه', day: '۱۰' },
|
||||||
|
{ weekday: 'جمعه', day: '۹' },
|
||||||
|
],
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.student-dashboard {
|
.dashboard {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
gap: 2rem;
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__main {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__stats {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 0.875rem;
|
||||||
|
|
||||||
|
@media (min-width: 640px) {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__activities {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 1.25rem;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__activity {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__pill {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.75rem 1.25rem;
|
||||||
|
background: rgba(255, 255, 255, 58%);
|
||||||
|
box-shadow: 0 6.75px 19.425px rgba(0, 0, 0, 4%);
|
||||||
|
border-radius: 0.9375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__pill-icon {
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__pill-label {
|
||||||
|
order: 1;
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
color: #4b4b4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__aside {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1.5rem;
|
gap: 1.5rem;
|
||||||
|
|
||||||
&__welcome {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
gap: 0.625rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__flower {
|
|
||||||
object-fit: contain;
|
|
||||||
max-height: 2.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__hi {
|
|
||||||
font-family: var(--font-family-fa);
|
|
||||||
font-weight: 400;
|
|
||||||
font-size: 1rem;
|
|
||||||
color: var(--color-prim-gray);
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__greeting {
|
|
||||||
font-family: var(--font-family-fa);
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 1rem;
|
|
||||||
margin: 0;
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
@media (min-width: 1024px) {
|
||||||
font-size: 1.5rem;
|
width: 19.625rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border-inline-start: 1px solid #e6e6e6;
|
||||||
|
padding-inline-start: 2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__placeholder {
|
|
||||||
font-family: var(--font-family-fa);
|
|
||||||
font-size: 0.875rem;
|
|
||||||
color: var(--color-prim-gray);
|
|
||||||
text-align: center;
|
|
||||||
padding: 3rem 0;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 1rem;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
<template>
|
||||||
|
<div class="activity-card">
|
||||||
|
<SvgIcon name="card-corner-arrow" :size="'1.5rem'" class="activity-card__corner" />
|
||||||
|
|
||||||
|
<div class="activity-card__thumb">
|
||||||
|
<SvgIcon name="play" :size="'1.5rem'" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="activity-card__body">
|
||||||
|
<p class="activity-card__title">{{ title }}</p>
|
||||||
|
|
||||||
|
<div class="activity-card__meta">
|
||||||
|
<SvgIcon :name="metaIcon" :size="'0.875rem'" class="activity-card__meta-icon" />
|
||||||
|
<div class="activity-card__rows">
|
||||||
|
<p v-for="(row, i) in meta" :key="i" class="activity-card__row">
|
||||||
|
<span class="activity-card__row-label">{{ row.label }}</span>
|
||||||
|
<span
|
||||||
|
class="activity-card__row-value"
|
||||||
|
:class="{ 'activity-card__row-value--num': row.numeric }"
|
||||||
|
>
|
||||||
|
{{ row.value }}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import SvgIcon from '@/components/icons/SvgIcon.vue'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
title: { type: String, default: '' },
|
||||||
|
/** rows of { label, value, numeric? } */
|
||||||
|
meta: { type: Array, default: () => [] },
|
||||||
|
/** @type {import('vue').PropType<import('@/components/icons/icon-names').IconName>} */
|
||||||
|
metaIcon: { type: String, default: 'calendar' },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.activity-card {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 0.875rem 1rem;
|
||||||
|
min-height: 5.9375rem;
|
||||||
|
background: rgba(255, 255, 255, 58%);
|
||||||
|
box-shadow: 0 6.75px 19.425px rgba(0, 0, 0, 4%);
|
||||||
|
border-radius: 0.9375rem;
|
||||||
|
|
||||||
|
&__corner {
|
||||||
|
position: absolute;
|
||||||
|
inset-block-start: 0.75rem;
|
||||||
|
inset-inline-end: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__thumb {
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 3.6875rem;
|
||||||
|
height: 3.6875rem;
|
||||||
|
background: #f4f4f4;
|
||||||
|
border-radius: 0.9375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.625rem;
|
||||||
|
text-align: start;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
margin: 0;
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: #4b4b4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta-icon {
|
||||||
|
order: 2;
|
||||||
|
margin-top: 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__rows {
|
||||||
|
order: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.375rem;
|
||||||
|
margin: 0;
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
color: #4b4b4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__row-value {
|
||||||
|
&--num {
|
||||||
|
font-family: var(--font-family-number-fa);
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<template>
|
||||||
|
<div class="calendar">
|
||||||
|
<p class="calendar__title">{{ monthLabel }}</p>
|
||||||
|
|
||||||
|
<div class="calendar__week">
|
||||||
|
<div
|
||||||
|
v-for="(d, i) in days"
|
||||||
|
:key="i"
|
||||||
|
class="calendar__day"
|
||||||
|
:class="{ 'calendar__day--active': d.selected }"
|
||||||
|
>
|
||||||
|
<span v-if="d.marker" class="calendar__marker" />
|
||||||
|
<span class="calendar__weekday">{{ d.weekday }}</span>
|
||||||
|
<span class="calendar__date">{{ d.day }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
defineProps({
|
||||||
|
monthLabel: { type: String, default: '' },
|
||||||
|
/** ordered right-to-left: { weekday, day, selected?, marker? } */
|
||||||
|
days: { type: Array, default: () => [] },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.calendar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 1.125rem 1rem;
|
||||||
|
background: rgba(255, 255, 255, 58%);
|
||||||
|
box-shadow: 0 6.75px 19.425px rgba(0, 0, 0, 4%);
|
||||||
|
border-radius: 0.9375rem;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
margin: 0;
|
||||||
|
text-align: start;
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__week {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__day {
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 0.375rem 0.125rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
background: var(--color-secondary);
|
||||||
|
box-shadow: 0 9px 9.75px rgba(0, 112, 116, 19%);
|
||||||
|
|
||||||
|
.calendar__weekday,
|
||||||
|
.calendar__date {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__marker {
|
||||||
|
position: absolute;
|
||||||
|
inset-block-start: 0.125rem;
|
||||||
|
inset-inline-start: 0.25rem;
|
||||||
|
width: 0.25rem;
|
||||||
|
height: 0.25rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--color-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__weekday {
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.625rem;
|
||||||
|
color: #828282;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__date {
|
||||||
|
font-family: var(--font-family-number-fa);
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: #717171;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
<template>
|
||||||
|
<div class="profile-card">
|
||||||
|
<div class="profile-card__avatar">
|
||||||
|
<img v-if="avatarUrl" :src="avatarUrl" :alt="name" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="profile-card__name">{{ name }}</p>
|
||||||
|
|
||||||
|
<div class="profile-card__location">
|
||||||
|
<SvgIcon name="map-pin-simple-area" :size="'0.9375rem'" />
|
||||||
|
<span>{{ location }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="profile-card__stats">
|
||||||
|
<div v-for="(stat, i) in stats" :key="i" class="profile-card__stat">
|
||||||
|
<span class="profile-card__stat-label">{{ stat.label }}</span>
|
||||||
|
<span class="profile-card__stat-value">
|
||||||
|
{{ stat.value }}
|
||||||
|
<span class="profile-card__stat-unit">{{ stat.unit }}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import SvgIcon from '@/components/icons/SvgIcon.vue'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
name: { type: String, default: '' },
|
||||||
|
location: { type: String, default: '' },
|
||||||
|
avatarUrl: { type: String, default: '' },
|
||||||
|
/** mini-stats of { label, value, unit } */
|
||||||
|
stats: { type: Array, default: () => [] },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.profile-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding: 2rem 1.25rem 1.5rem;
|
||||||
|
background: rgba(255, 255, 255, 58%);
|
||||||
|
box-shadow: 0 6.75px 19.425px rgba(0, 0, 0, 4%);
|
||||||
|
border-radius: 0.9375rem;
|
||||||
|
|
||||||
|
&__avatar {
|
||||||
|
width: 7.75rem;
|
||||||
|
height: 7.75rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #f4f4f4;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__name {
|
||||||
|
margin: 0;
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__location {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: #989898;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__stats {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__stat {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__stat-label {
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.6875rem;
|
||||||
|
color: #a7a7a7;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__stat-value {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 0.25rem;
|
||||||
|
font-family: var(--font-family-number-fa);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 1.5625rem;
|
||||||
|
color: #818181;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__stat-unit {
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: #929292;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
<template>
|
||||||
|
<div class="stat-card">
|
||||||
|
<SvgIcon name="card-corner-arrow" :size="'1.5rem'" class="stat-card__corner" />
|
||||||
|
|
||||||
|
<div class="stat-card__head">
|
||||||
|
<SvgIcon :name="icon" :size="'1.0625rem'" class="stat-card__head-icon" />
|
||||||
|
<span class="stat-card__label">{{ label }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-card__body">
|
||||||
|
<span class="stat-card__value">{{ value }}</span>
|
||||||
|
<div class="stat-card__meta">
|
||||||
|
<span class="stat-card__unit">{{ unit }}</span>
|
||||||
|
<span class="stat-card__subtitle">{{ subtitle }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import SvgIcon from '@/components/icons/SvgIcon.vue'
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
/** @type {import('vue').PropType<import('@/components/icons/icon-names').IconName>} */
|
||||||
|
icon: { type: String, required: true },
|
||||||
|
label: { type: String, default: '' },
|
||||||
|
value: { type: [String, Number], default: '' },
|
||||||
|
unit: { type: String, default: '' },
|
||||||
|
subtitle: { type: String, default: '' },
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.stat-card {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
padding: 1.125rem 1.25rem;
|
||||||
|
min-height: 8.75rem;
|
||||||
|
background: rgba(255, 255, 255, 58%);
|
||||||
|
box-shadow: 0 6.75px 19.425px rgba(0, 0, 0, 4%);
|
||||||
|
border-radius: 0.9375rem;
|
||||||
|
|
||||||
|
&__corner {
|
||||||
|
position: absolute;
|
||||||
|
inset-block-start: 0.875rem;
|
||||||
|
inset-inline-end: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__head {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 0.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__head-icon {
|
||||||
|
order: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
order: 1;
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
color: #4b4b4b;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__body {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 0.625rem;
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
font-family: var(--font-family-number-fa);
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 4rem;
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--color-primary);
|
||||||
|
text-shadow: 0 5.25px 8.625px rgba(243, 102, 117, 18%);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__unit {
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
color: #6e6e6e;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__subtitle {
|
||||||
|
font-family: var(--font-family-fa);
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
color: #6e6e6e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user