Files
Lucky_Wheel/apps/admin/src/components/mobile/MobileTopBar.vue
T
s.esmaeili afde44ab8a fix(core): resolve local client url redirects and stabilize dev environment
- enforce localhost:5174 for wheel campaign client URL in local development
- lock vite dev server ports using strictPort on admin (5173) and client (5174)
- sanitize .env.example and remove hardcoded staging domain
- configure root dev orchestration and docker multi-stage build context
2026-09-13 02:02:46 +03:30

155 lines
2.9 KiB
Vue

<script setup lang="ts">
import { ArrowRightOutlined } from '@ant-design/icons-vue';
import { computed } from 'vue';
import { useRouter } from 'vue-router';
const props = withDefaults(
defineProps<{
title?: string;
showBack?: boolean;
transparent?: boolean;
}>(),
{
title: '',
showBack: false,
transparent: false,
},
);
const emit = defineEmits<{
back: [];
}>();
const router = useRouter();
const canGoBack = computed(() => props.showBack);
function handleBack() {
emit('back');
if (window.history.length > 1) {
router.back();
} else {
router.push('/m/dashboard');
}
}
</script>
<template>
<header class="m-topbar" :class="{ 'm-topbar--transparent': transparent }">
<div class="m-topbar__safe" />
<div class="m-topbar__inner">
<div class="m-topbar__side m-topbar__side--start">
<button
v-if="canGoBack"
type="button"
class="m-topbar__btn"
aria-label="بازگشت"
@click="handleBack"
>
<ArrowRightOutlined />
</button>
<slot name="start" />
</div>
<h1 class="m-topbar__title">{{ title }}</h1>
<div class="m-topbar__side m-topbar__side--end">
<slot name="actions" />
</div>
</div>
</header>
</template>
<style scoped>
.m-topbar {
position: sticky;
top: 0;
z-index: 100;
background: linear-gradient(135deg, #4f46e5 0%, #6366f1 55%, #7c3aed 100%);
color: #fff;
box-shadow: 0 4px 20px rgba(79, 70, 229, 0.28);
}
.m-topbar--transparent {
background: transparent;
box-shadow: none;
}
.m-topbar__safe {
height: env(safe-area-inset-top, 0px);
}
.m-topbar__inner {
height: 56px;
display: grid;
grid-template-columns: 72px 1fr 72px;
align-items: center;
padding: 0 8px;
}
.m-topbar__title {
margin: 0;
text-align: center;
font-size: 16px;
font-weight: 700;
letter-spacing: -0.01em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #fff;
}
.m-topbar__side {
display: flex;
align-items: center;
gap: 4px;
min-height: 48px;
}
.m-topbar__side--start {
justify-content: flex-start;
}
.m-topbar__side--end {
justify-content: flex-end;
}
.m-topbar__btn {
width: 44px;
height: 44px;
border: none;
border-radius: 12px;
background: rgba(255, 255, 255, 0.14);
color: #fff;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 16px;
cursor: pointer;
}
.m-topbar__btn:active {
background: rgba(255, 255, 255, 0.28);
transform: scale(0.96);
}
:deep(.m-topbar-action) {
width: 44px;
height: 44px;
border: none;
border-radius: 12px;
background: rgba(255, 255, 255, 0.14);
color: #fff;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 16px;
cursor: pointer;
}
:deep(.m-topbar-action:active) {
background: rgba(255, 255, 255, 0.28);
transform: scale(0.96);
}
</style>