Ship the new logo assets, set primary to #10897d, and polish sidebar/home-hero UX around roles, org switcher, and the ask bar.
394 lines
8.7 KiB
Vue
394 lines
8.7 KiB
Vue
<script setup lang="ts">
|
||
import { computed } from 'vue';
|
||
import { SendOutlined } from '@/icons/ant-bridge';
|
||
import {
|
||
Button as AButton,
|
||
Input as AInput,
|
||
Typography,
|
||
} from 'ant-design-vue';
|
||
import { brand } from '@mento/shared';
|
||
import { useAuthStore } from '@/stores/auth';
|
||
|
||
const props = defineProps<{
|
||
greeting: string;
|
||
firstName: string;
|
||
userInitial: string;
|
||
askQuery: string;
|
||
asking?: boolean;
|
||
askAnswer?: string;
|
||
askError?: string;
|
||
statusText?: string;
|
||
}>();
|
||
|
||
const emit = defineEmits<{
|
||
'update:askQuery': [value: string];
|
||
ask: [];
|
||
}>();
|
||
|
||
const auth = useAuthStore();
|
||
const { Title: ATypographyTitle, Text: ATypographyText, Paragraph: ATypographyParagraph } =
|
||
Typography;
|
||
|
||
/** فقط عکس واقعی کاربر؛ پیشفرض عمومی را نشان نده */
|
||
const hasCustomPhoto = computed(() => Boolean(auth.user?.hasAvatar));
|
||
|
||
const shortcutLabel = computed(() =>
|
||
typeof navigator !== 'undefined' && /Mac|iPhone|iPad/i.test(navigator.platform)
|
||
? '⌘K'
|
||
: 'Ctrl+K',
|
||
);
|
||
|
||
const statusMessage = computed(() => {
|
||
if (props.asking) return props.statusText || 'در حال پاسخ…';
|
||
if (props.askError) return props.askError;
|
||
if (props.askAnswer) return props.askAnswer;
|
||
return '';
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<div class="flex flex-col gap-3">
|
||
<div class="home-hero">
|
||
<div class="home-hero__gradient" aria-hidden="true" />
|
||
<div class="home-hero__pattern" aria-hidden="true" />
|
||
<div class="home-hero__orb home-hero__orb--start" aria-hidden="true" />
|
||
<div class="home-hero__orb home-hero__orb--end" aria-hidden="true" />
|
||
|
||
<div class="home-hero__row">
|
||
<div class="home-hero__greet">
|
||
<div class="home-hero__identity" :aria-label="firstName">
|
||
<img
|
||
v-if="hasCustomPhoto"
|
||
:src="auth.avatarSrc"
|
||
:alt="firstName"
|
||
class="home-hero__photo"
|
||
/>
|
||
<span v-else class="home-hero__monogram" aria-hidden="true">
|
||
{{ userInitial }}
|
||
</span>
|
||
<span class="home-hero__online" title="آنلاین" aria-hidden="true" />
|
||
</div>
|
||
<div class="home-hero__copy">
|
||
<p class="home-hero__brand">{{ brand.nameFa }}</p>
|
||
<a-typography-title :level="4" class="home-hero__title">
|
||
{{ greeting }}، {{ firstName }}
|
||
</a-typography-title>
|
||
<a-typography-text class="home-hero__subtitle">
|
||
از دادهها بپرسید یا کار امروز را از همینجا شروع کنید
|
||
</a-typography-text>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="home-hero__ask">
|
||
<a-input
|
||
id="home-hero-ask"
|
||
:value="askQuery"
|
||
:placeholder="brand.askPlaceholderFa"
|
||
:disabled="asking"
|
||
:bordered="false"
|
||
class="home-hero__ask-input"
|
||
@update:value="emit('update:askQuery', $event)"
|
||
@press-enter="emit('ask')"
|
||
/>
|
||
<kbd class="home-hero__ask-kbd">{{ shortcutLabel }}</kbd>
|
||
<a-button
|
||
type="primary"
|
||
shape="round"
|
||
class="home-hero__ask-btn"
|
||
:disabled="asking"
|
||
:loading="asking"
|
||
aria-label="ارسال"
|
||
@click="emit('ask')"
|
||
>
|
||
<span class="home-hero__ask-btn-inner">
|
||
<SendOutlined />
|
||
<span class="home-hero__ask-label">بپرس</span>
|
||
</span>
|
||
</a-button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div
|
||
v-if="statusMessage"
|
||
class="rounded-xl border px-3.5 py-2.5"
|
||
:class="
|
||
askError
|
||
? 'border-rose-200 bg-rose-50/70'
|
||
: asking
|
||
? 'border-emerald-200/70 bg-emerald-50/50'
|
||
: 'border-slate-200 bg-slate-50/80'
|
||
"
|
||
>
|
||
<a-typography-paragraph
|
||
:type="askError ? 'danger' : 'secondary'"
|
||
:ellipsis="{ rows: 3 }"
|
||
class="!mb-0 !text-sm"
|
||
>
|
||
{{ statusMessage }}
|
||
</a-typography-paragraph>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.home-hero {
|
||
position: relative;
|
||
display: block;
|
||
width: 100%;
|
||
max-width: 100%;
|
||
min-width: 0;
|
||
box-sizing: border-box;
|
||
overflow: hidden;
|
||
border-radius: 1rem;
|
||
border: 1px solid rgb(16 137 125 / 0.28);
|
||
box-shadow: 0 1px 2px rgb(15 23 42 / 0.04);
|
||
}
|
||
|
||
.home-hero__gradient,
|
||
.home-hero__pattern,
|
||
.home-hero__orb {
|
||
pointer-events: none;
|
||
position: absolute;
|
||
}
|
||
|
||
.home-hero__gradient,
|
||
.home-hero__pattern {
|
||
inset: 0;
|
||
}
|
||
|
||
.home-hero__gradient {
|
||
background:
|
||
linear-gradient(
|
||
115deg,
|
||
#eef8f7 0%,
|
||
#d0ebe8 28%,
|
||
#c5e6e2 55%,
|
||
#eef8f7 78%,
|
||
#ffffff 100%
|
||
);
|
||
}
|
||
|
||
.home-hero__pattern {
|
||
opacity: 0.45;
|
||
background-image:
|
||
radial-gradient(circle at 1px 1px, rgba(16, 137, 125, 0.28) 1px, transparent 0),
|
||
linear-gradient(
|
||
135deg,
|
||
rgba(16, 137, 125, 0.08) 25%,
|
||
transparent 25%,
|
||
transparent 50%,
|
||
rgba(16, 137, 125, 0.08) 50%,
|
||
rgba(16, 137, 125, 0.08) 75%,
|
||
transparent 75%,
|
||
transparent
|
||
);
|
||
background-size:
|
||
18px 18px,
|
||
28px 28px;
|
||
mask-image: linear-gradient(to left, rgba(0, 0, 0, 0.85), rgba(0, 0, 0, 0.25));
|
||
}
|
||
|
||
.home-hero__orb {
|
||
border-radius: 999px;
|
||
filter: blur(48px);
|
||
}
|
||
|
||
.home-hero__orb--start {
|
||
inset-inline-end: -5rem;
|
||
top: -6rem;
|
||
width: 13rem;
|
||
height: 13rem;
|
||
background: rgb(22 193 168 / 0.22);
|
||
}
|
||
|
||
.home-hero__orb--end {
|
||
inset-inline-start: -4rem;
|
||
bottom: -5rem;
|
||
width: 12rem;
|
||
height: 12rem;
|
||
background: rgb(16 137 125 / 0.16);
|
||
}
|
||
|
||
.home-hero__row {
|
||
position: relative;
|
||
z-index: 1;
|
||
display: grid;
|
||
grid-template-columns: auto minmax(0, 1fr);
|
||
align-items: center;
|
||
gap: 1rem;
|
||
width: 100%;
|
||
max-width: 100%;
|
||
min-width: 0;
|
||
box-sizing: border-box;
|
||
padding: 1rem 1.25rem;
|
||
}
|
||
|
||
.home-hero__greet {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.875rem;
|
||
min-width: 0;
|
||
max-width: 22rem;
|
||
}
|
||
|
||
.home-hero__identity {
|
||
position: relative;
|
||
flex-shrink: 0;
|
||
width: 3rem;
|
||
height: 3rem;
|
||
}
|
||
|
||
.home-hero__photo,
|
||
.home-hero__monogram {
|
||
display: flex;
|
||
width: 100%;
|
||
height: 100%;
|
||
border-radius: 0.85rem;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.home-hero__monogram {
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 1.1rem;
|
||
font-weight: 800;
|
||
color: #eef8f7;
|
||
background: linear-gradient(160deg, #16c1a8 0%, #10897d 100%);
|
||
letter-spacing: -0.02em;
|
||
user-select: none;
|
||
}
|
||
|
||
.home-hero__online {
|
||
position: absolute;
|
||
inset-inline-start: 0;
|
||
bottom: 0;
|
||
width: 0.7rem;
|
||
height: 0.7rem;
|
||
border-radius: 999px;
|
||
background: #10897d;
|
||
border: 2px solid #fff;
|
||
}
|
||
|
||
.home-hero__copy {
|
||
min-width: 0;
|
||
}
|
||
|
||
.home-hero__brand {
|
||
margin: 0;
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
letter-spacing: 0.02em;
|
||
color: rgb(4 120 87 / 0.8);
|
||
}
|
||
|
||
.home-hero__title {
|
||
margin: 0.125rem 0 0 !important;
|
||
color: #1e293b !important;
|
||
font-size: 1.125rem !important;
|
||
font-weight: 800 !important;
|
||
line-height: 1.75rem !important;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.home-hero__subtitle {
|
||
display: block !important;
|
||
margin-top: 0.125rem !important;
|
||
color: #64748b !important;
|
||
font-size: 0.875rem !important;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.home-hero__ask {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 0.5rem;
|
||
width: 100%;
|
||
min-width: 0;
|
||
box-sizing: border-box;
|
||
padding-block: 0.375rem;
|
||
padding-inline: 0.75rem 0.5rem;
|
||
background: #fff;
|
||
border: 1px solid rgb(255 255 255 / 0.8);
|
||
border-radius: 1rem;
|
||
box-shadow:
|
||
0 4px 12px rgb(6 78 59 / 0.05),
|
||
0 1px 2px rgb(15 23 42 / 0.04);
|
||
transition:
|
||
border-color 0.15s ease,
|
||
box-shadow 0.15s ease;
|
||
}
|
||
|
||
.home-hero__ask:focus-within {
|
||
border-color: #16c1a8;
|
||
box-shadow:
|
||
0 0 0 2px rgb(16 137 125 / 0.18),
|
||
0 4px 12px rgb(10 92 84 / 0.06);
|
||
}
|
||
|
||
.home-hero__ask-input {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
background: transparent !important;
|
||
}
|
||
|
||
.home-hero__ask-kbd {
|
||
display: none;
|
||
flex-shrink: 0;
|
||
align-items: center;
|
||
padding: 0.25rem 0.5rem;
|
||
border-radius: 0.5rem;
|
||
border: 1px solid #e2e8f0;
|
||
background: #f8fafc;
|
||
color: #94a3b8;
|
||
font-size: 11px;
|
||
font-family: ui-sans-serif, system-ui, sans-serif;
|
||
}
|
||
|
||
.home-hero__ask-btn {
|
||
display: inline-flex !important;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.home-hero__ask-btn-inner {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 0.35rem;
|
||
line-height: 1;
|
||
}
|
||
|
||
.home-hero__ask-label {
|
||
display: none;
|
||
}
|
||
|
||
@media (min-width: 640px) {
|
||
.home-hero__ask-kbd {
|
||
display: inline-flex;
|
||
}
|
||
|
||
.home-hero__ask-label {
|
||
display: inline;
|
||
}
|
||
|
||
.home-hero__title {
|
||
font-size: 1.25rem !important;
|
||
}
|
||
}
|
||
|
||
@media (max-width: 1023px) {
|
||
.home-hero__row {
|
||
grid-template-columns: minmax(0, 1fr);
|
||
}
|
||
|
||
.home-hero__greet {
|
||
max-width: none;
|
||
}
|
||
}
|
||
</style>
|