mirror of
https://git.meshkee.com/Meshkee/dashboards.git
synced 2026-08-11 22:30:58 +04:30
Add customer and business user-product flows across dashboards.
Ship my-products / customer-products UI with gallery uploads, status controls, module gating, and related shared UI polish. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
c5bdaad16b
commit
1271d96539
@@ -4,7 +4,7 @@ import styles from './AddressListEditor.module.css'
|
||||
export type CityOption = {
|
||||
id: string
|
||||
parentId: string | null
|
||||
level: 'country' | 'province' | 'city'
|
||||
level: 'country' | 'province' | 'city' | 'district'
|
||||
nameFa: string
|
||||
nameEn: string
|
||||
landlineCode: string | null
|
||||
|
||||
@@ -4,9 +4,16 @@
|
||||
align-items: center;
|
||||
height: 38px;
|
||||
border-radius: 50px;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
background: linear-gradient(
|
||||
145deg,
|
||||
color-mix(in srgb, var(--elevated-surface) 78%, transparent) 0%,
|
||||
color-mix(in srgb, var(--glass-bg) 55%, transparent) 55%,
|
||||
color-mix(in srgb, var(--surface) 42%, transparent) 100%
|
||||
);
|
||||
backdrop-filter: blur(18px);
|
||||
-webkit-backdrop-filter: blur(18px);
|
||||
border: 1px solid var(--glass-border);
|
||||
transition: box-shadow 0.2s, border-color 0.2s;
|
||||
transition: box-shadow 0.2s, border-color 0.2s, background 0.2s;
|
||||
}
|
||||
|
||||
.wrap:hover,
|
||||
@@ -20,6 +27,7 @@
|
||||
inset-inline-start: 12px;
|
||||
color: var(--text-secondary);
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.chevron {
|
||||
@@ -27,27 +35,37 @@
|
||||
inset-inline-end: 10px;
|
||||
color: var(--text-muted);
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.select {
|
||||
/* Beat global `select` + `html[data-theme='dark'] select` so the pill stays one surface */
|
||||
.wrap .select {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
height: 100%;
|
||||
min-width: 72px;
|
||||
min-height: 0;
|
||||
min-width: 76px;
|
||||
padding-block: 0;
|
||||
padding-inline: 34px 28px;
|
||||
border: none;
|
||||
border-radius: 50px;
|
||||
background: transparent;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
box-shadow: none;
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
font-family: var(--font-ui);
|
||||
line-height: 1;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.select:focus {
|
||||
.wrap .select:focus {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
padding: 28px;
|
||||
background: var(--glass-bg);
|
||||
backdrop-filter: blur(20px);
|
||||
@@ -19,7 +20,8 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, var(--primary-light) 0%, rgba(219, 234, 254, 0.5) 100%);
|
||||
background: linear-gradient(135deg, var(--icon-bg) 0%, var(--icon-bg-end) 100%);
|
||||
border: 1px solid rgba(var(--primary-rgb) / 0.22);
|
||||
border-radius: var(--radius-sm);
|
||||
color: var(--primary);
|
||||
margin-bottom: 20px;
|
||||
@@ -50,6 +52,9 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
min-height: 36px;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.link {
|
||||
@@ -58,28 +63,74 @@
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.countMeta {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px 8px;
|
||||
height: 36px;
|
||||
max-width: calc(100% - 48px);
|
||||
padding: 0 14px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 999px;
|
||||
background: rgba(var(--primary-rgb) / 0.1);
|
||||
color: var(--primary);
|
||||
transition:
|
||||
background 0.35s ease,
|
||||
color 0.35s ease;
|
||||
}
|
||||
|
||||
.countValue {
|
||||
font-family: var(--font-en), var(--font-ui), sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
font-variant-numeric: tabular-nums;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.countLabel {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: inherit;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.card:hover .countMeta {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.card:hover .countLabel {
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.arrowBtn {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: rgba(var(--primary-rgb) / 0.1);
|
||||
color: var(--primary);
|
||||
transition: background 0.2s, transform 0.2s;
|
||||
transition:
|
||||
background 0.35s ease,
|
||||
color 0.35s ease;
|
||||
}
|
||||
|
||||
.arrowIcon {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.card:hover .arrowBtn {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
:global([dir='rtl']) .arrowBtn {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
:global([dir='rtl']) .card:hover .arrowBtn {
|
||||
transform: scaleX(-1) translateX(2px);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,12 @@ interface SectionCardProps {
|
||||
icon: LucideIcon
|
||||
title: string
|
||||
description: string
|
||||
linkText: string
|
||||
/** Legacy footer link text; prefer count + countLabel when available. */
|
||||
linkText?: string
|
||||
href: string
|
||||
/** Entity total shown beside the arrow; omit for sections without a count. */
|
||||
count?: number | null
|
||||
countLabel?: string
|
||||
}
|
||||
|
||||
export function SectionCard({
|
||||
@@ -16,7 +20,14 @@ export function SectionCard({
|
||||
description,
|
||||
linkText,
|
||||
href,
|
||||
count,
|
||||
countLabel,
|
||||
}: SectionCardProps) {
|
||||
const showCount = typeof count === 'number' && Number.isFinite(count)
|
||||
const formattedCount = showCount
|
||||
? new Intl.NumberFormat('en-US').format(count)
|
||||
: null
|
||||
|
||||
return (
|
||||
<Link to={href} className={styles.card} data-card-hover>
|
||||
<div className={styles.iconWrap}>
|
||||
@@ -27,9 +38,20 @@ export function SectionCard({
|
||||
<p className={styles.description}>{description}</p>
|
||||
|
||||
<div className={styles.footer}>
|
||||
<span className={styles.link}>{linkText}</span>
|
||||
{formattedCount !== null && countLabel ? (
|
||||
<div className={styles.countMeta}>
|
||||
<span className={styles.countValue} lang="en" dir="ltr">
|
||||
{formattedCount}
|
||||
</span>
|
||||
<span className={styles.countLabel}>{countLabel}</span>
|
||||
</div>
|
||||
) : linkText ? (
|
||||
<span className={styles.link}>{linkText}</span>
|
||||
) : (
|
||||
<span />
|
||||
)}
|
||||
<span className={styles.arrowBtn} aria-hidden="true">
|
||||
<ArrowRight size={18} />
|
||||
<ArrowRight size={18} className={styles.arrowIcon} />
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
color: var(--text-primary);
|
||||
background: rgba(255, 255, 255, 0.55);
|
||||
background: var(--elevated-surface);
|
||||
backdrop-filter: blur(var(--blur-glass));
|
||||
-webkit-backdrop-filter: blur(var(--blur-glass));
|
||||
border: 1px solid var(--glass-border);
|
||||
|
||||
Reference in New Issue
Block a user