feat(convert,assets): convert page route and assets portfolio chart
Add convert mobile/desktop views and assets chart from price history; polish calculator and wallet/home integration. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -164,8 +164,9 @@ function formatRings(value: number) {
|
||||
.copper-convert {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
gap: 0.75rem;
|
||||
text-align: right;
|
||||
color: #334155;
|
||||
}
|
||||
|
||||
.copper-convert__lead {
|
||||
@@ -175,28 +176,13 @@ function formatRings(value: number) {
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.copper-convert__panel {
|
||||
position: relative;
|
||||
padding: 0.75rem 0.875rem 0.7rem;
|
||||
border-radius: 1rem;
|
||||
background: linear-gradient(145deg, #0f2744 0%, #152f4f 48%, #1a365d 100%);
|
||||
border: 1px solid rgba(201, 160, 98, 0.35);
|
||||
box-shadow:
|
||||
0 12px 28px rgba(15, 39, 68, 0.22),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.06);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.copper-convert__panel::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -40px;
|
||||
inset-inline-end: -30px;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(232, 180, 140, 0.28) 0%, transparent 70%);
|
||||
pointer-events: none;
|
||||
.copper-convert__panel,
|
||||
.copper-convert__form,
|
||||
.copper-convert__result {
|
||||
padding: 0.875rem;
|
||||
border-radius: 0.875rem;
|
||||
background: #fff;
|
||||
border: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.copper-convert__panel-head {
|
||||
@@ -208,17 +194,18 @@ function formatRings(value: number) {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.copper-convert__panel-kicker {
|
||||
.copper-convert__panel-kicker,
|
||||
.copper-convert__result-kicker {
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
color: rgba(201, 160, 98, 0.95);
|
||||
color: var(--colorPrimary, #2563eb);
|
||||
}
|
||||
|
||||
.copper-convert__panel-title {
|
||||
.copper-convert__panel-title,
|
||||
.copper-convert__result-title {
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 800;
|
||||
color: #f8fafc;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.copper-convert__price-group {
|
||||
@@ -230,7 +217,7 @@ function formatRings(value: number) {
|
||||
.copper-convert__price-group--wire {
|
||||
margin-bottom: 0;
|
||||
padding-top: 0.65rem;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-top: 1px solid #f1f5f9;
|
||||
}
|
||||
|
||||
.copper-convert__group-label {
|
||||
@@ -238,7 +225,7 @@ function formatRings(value: number) {
|
||||
margin-bottom: 0.45rem;
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
color: rgba(226, 232, 240, 0.75);
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.copper-convert__price-grid {
|
||||
@@ -258,29 +245,29 @@ function formatRings(value: number) {
|
||||
min-width: 0;
|
||||
padding: 0.45rem 0.5rem;
|
||||
border-radius: 0.65rem;
|
||||
background: rgba(255, 255, 255, 0.06);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.copper-convert__chip--accent {
|
||||
background: rgba(201, 160, 98, 0.12);
|
||||
border-color: rgba(201, 160, 98, 0.35);
|
||||
background: #eff5f3;
|
||||
border-color: #d4e3de;
|
||||
}
|
||||
|
||||
.copper-convert__chip--muted .copper-convert__chip-value {
|
||||
color: rgba(248, 250, 252, 0.45);
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.copper-convert__chip-label {
|
||||
font-size: 0.625rem;
|
||||
line-height: 1.45;
|
||||
color: rgba(226, 232, 240, 0.85);
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.copper-convert__chip-value {
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 700;
|
||||
color: #f8fafc;
|
||||
color: #0f172a;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
@@ -290,11 +277,6 @@ function formatRings(value: number) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.65rem;
|
||||
margin-top: 0.125rem;
|
||||
padding: 0.75rem 0.875rem;
|
||||
border-radius: 1rem;
|
||||
background: #faf8f5;
|
||||
border: 1px solid rgba(201, 160, 98, 0.22);
|
||||
}
|
||||
|
||||
.copper-convert__field-label {
|
||||
@@ -327,9 +309,9 @@ function formatRings(value: number) {
|
||||
}
|
||||
|
||||
.copper-convert__pill--active {
|
||||
color: #0f2744;
|
||||
color: var(--colorPrimary, #2563eb);
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 8px rgba(15, 39, 68, 0.12);
|
||||
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.copper-convert__weight-wrap {
|
||||
@@ -352,7 +334,7 @@ function formatRings(value: number) {
|
||||
background: transparent;
|
||||
font-size: 1.125rem;
|
||||
font-weight: 800;
|
||||
color: #0f2744;
|
||||
color: #0f172a;
|
||||
text-align: right;
|
||||
direction: ltr;
|
||||
}
|
||||
@@ -367,16 +349,13 @@ function formatRings(value: number) {
|
||||
flex-shrink: 0;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 800;
|
||||
color: #c9a062;
|
||||
color: var(--colorPrimary, #2563eb);
|
||||
}
|
||||
|
||||
.copper-convert__result {
|
||||
margin-top: 0.125rem;
|
||||
padding: 0.875rem;
|
||||
border-radius: 1rem;
|
||||
background: linear-gradient(180deg, #fff 0%, #faf8f5 100%);
|
||||
border: 1px solid rgba(201, 160, 98, 0.35);
|
||||
box-shadow: 0 8px 24px rgba(15, 39, 68, 0.08);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.copper-convert__result-head {
|
||||
@@ -386,17 +365,6 @@ function formatRings(value: number) {
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.copper-convert__result-kicker {
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 700;
|
||||
color: #c9a062;
|
||||
}
|
||||
|
||||
.copper-convert__result-title {
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 800;
|
||||
color: #0f2744;
|
||||
}
|
||||
|
||||
.copper-convert__rings {
|
||||
display: grid;
|
||||
@@ -410,23 +378,11 @@ function formatRings(value: number) {
|
||||
padding: 0.75rem 0.5rem;
|
||||
border-radius: 0.85rem;
|
||||
text-align: center;
|
||||
background: linear-gradient(160deg, #0f2744 0%, #1a365d 100%);
|
||||
border: 1px solid rgba(201, 160, 98, 0.4);
|
||||
background: #eff5f3;
|
||||
border: 1px solid #d4e3de;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.copper-convert__ring-card::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset-inline-start: 50%;
|
||||
bottom: -24px;
|
||||
width: 80px;
|
||||
height: 48px;
|
||||
transform: translateX(-50%);
|
||||
background: radial-gradient(ellipse, rgba(201, 160, 98, 0.35) 0%, transparent 70%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.copper-convert__ring-badge {
|
||||
display: inline-block;
|
||||
margin-bottom: 0.35rem;
|
||||
@@ -434,8 +390,8 @@ function formatRings(value: number) {
|
||||
border-radius: 999px;
|
||||
font-size: 0.625rem;
|
||||
font-weight: 700;
|
||||
color: #0f2744;
|
||||
background: rgba(201, 160, 98, 0.95);
|
||||
color: var(--colorPrimary, #2563eb);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.copper-convert__ring-count {
|
||||
@@ -443,20 +399,20 @@ function formatRings(value: number) {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 800;
|
||||
line-height: 1.2;
|
||||
color: #f8fafc;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.copper-convert__ring-caption {
|
||||
margin: 0.15rem 0 0;
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 600;
|
||||
color: rgba(226, 232, 240, 0.85);
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.copper-convert__ring-sub {
|
||||
margin: 0.35rem 0 0;
|
||||
font-size: 0.625rem;
|
||||
color: rgba(201, 160, 98, 0.9);
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.copper-convert__summary {
|
||||
@@ -479,7 +435,7 @@ function formatRings(value: number) {
|
||||
.copper-convert__summary-row strong {
|
||||
font-size: 0.8125rem;
|
||||
font-weight: 800;
|
||||
color: #0f2744;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.copper-convert__summary-row strong small {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import {
|
||||
computed,
|
||||
inject,
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
provide,
|
||||
ref,
|
||||
type ComputedRef,
|
||||
@@ -144,14 +146,14 @@ export function useCopperConvertPage() {
|
||||
}
|
||||
}
|
||||
|
||||
async function refreshLivePrices() {
|
||||
onMounted(() => {
|
||||
startLastPricePolling()
|
||||
await loadCatalog()
|
||||
}
|
||||
void loadCatalog()
|
||||
})
|
||||
|
||||
function stopLivePrices() {
|
||||
onUnmounted(() => {
|
||||
stopLastPricePolling()
|
||||
}
|
||||
})
|
||||
|
||||
const ctx: CopperConvertPageContext = {
|
||||
loading,
|
||||
@@ -163,7 +165,7 @@ export function useCopperConvertPage() {
|
||||
}
|
||||
|
||||
provide(COPPER_CONVERT_PAGE_KEY, ctx)
|
||||
return { ...ctx, refreshLivePrices, stopLivePrices, loadCatalog }
|
||||
return ctx
|
||||
}
|
||||
|
||||
export function useCopperConvertPageContext() {
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div class="dconvert">
|
||||
<div class="dconvert__container">
|
||||
<header class="dconvert-topbar">
|
||||
<button type="button" class="dconvert-topbar__back" @click="router.back()">
|
||||
<BasicIcon icon="vuesax-linear:arrow-right-1" size="18" />
|
||||
<span>بازگشت</span>
|
||||
</button>
|
||||
<div class="dconvert-topbar__meta">
|
||||
<p class="dconvert-topbar__eyebrow">محصول</p>
|
||||
<h1 class="dconvert-topbar__title">تبدیل محصول</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="dconvert-surface">
|
||||
<CopperConvertCalculator />
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import BasicIcon from '@/components/BasicPacks/BasicIcon.vue'
|
||||
import router from '@/router'
|
||||
import CopperConvertCalculator from '../components/CopperConvertCalculator.vue'
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.dconvert {
|
||||
min-height: 100%;
|
||||
padding: 1.25rem 1.5rem 2rem;
|
||||
}
|
||||
|
||||
.dconvert__container {
|
||||
max-width: 720px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.dconvert-topbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.dconvert-topbar__back {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--colorPrimary, #2563eb);
|
||||
font-family: inherit;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.dconvert-topbar__eyebrow {
|
||||
margin: 0;
|
||||
font-size: 0.75rem;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.dconvert-topbar__title {
|
||||
margin: 0;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 800;
|
||||
color: #0f172a;
|
||||
}
|
||||
|
||||
.dconvert-surface {
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.875rem;
|
||||
background: #fff;
|
||||
padding: 1.25rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<div class="convert-page-root">
|
||||
<DesktopConvertView v-show="isDesktop" />
|
||||
<MobileConvertView v-show="!isDesktop" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useDesktopBreakpoint } from '@/layouts/composables/useAppLayout'
|
||||
import { useCopperConvertPage } from './composables/useCopperConvertPage'
|
||||
import DesktopConvertView from './desktop/DesktopConvertView.vue'
|
||||
import MobileConvertView from './mobile/MobileConvertView.vue'
|
||||
|
||||
const isDesktop = useDesktopBreakpoint()
|
||||
|
||||
useCopperConvertPage()
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.convert-page-root {
|
||||
min-height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<MobilePageHeader title="تبدیل محصول" show-back />
|
||||
<div class="px-5 mpage-content pb-2">
|
||||
<div class="border-gray-200 border-1 rounded-xl p-4 relative bg-white">
|
||||
<CopperConvertCalculator />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import MobilePageHeader from '@/layouts/components/MobilePageHeader.vue'
|
||||
import CopperConvertCalculator from '../components/CopperConvertCalculator.vue'
|
||||
</script>
|
||||
Reference in New Issue
Block a user