Revamped the theming system with new SCSS variables for consistent styling across light and dark themes. Replaced static color values with dynamic variables for maintainability and improved theme adaptability. Updated components and layouts to use the new variables. - Moved theme plugin logic for optimized handling of theme cookies and attributes. - Enhanced `useThemes` composable for simplified client-side updates and SSR support. - Replaced redundant SCSS color definitions with centralized variables. - Improved page structure by introducing `ui-title` for reusable section headers. - Unified transitions and border-radius for consistent design language. Breaking Changes: Theming system restructured—migrate to `$main`, `$primary`, and related variables for SCSS colors. Remove usage of `--color-*` variables in templates and styles.
240 lines
No EOL
5.2 KiB
Vue
240 lines
No EOL
5.2 KiB
Vue
<template>
|
|
<div class="settings">
|
|
<div class="settings__top">
|
|
<div class="settings__top-left">
|
|
<div class="settings__avatar">
|
|
<input type="file" id="avatar" @change="uploadAvatar" />
|
|
<label for="avatar">
|
|
<nuxt-img
|
|
class="settings__avatar-image"
|
|
v-if="user?.avatar"
|
|
:src="user?.avatar"
|
|
alt="avatar"
|
|
format="webp"
|
|
densities="x1"
|
|
/>
|
|
<icon name="clarity:avatar-line" size="40" v-else />
|
|
<span class="settings__avatar-inner">
|
|
<icon name="material-symbols:upload" size="40" />
|
|
</span>
|
|
</label>
|
|
</div>
|
|
<div class="settings__top-inner">
|
|
<h2>{{ user?.firstName }} {{ user?.lastName }}</h2>
|
|
<p>{{ t('profile.settings.joinData') }}: {{ joinData }}</p>
|
|
</div>
|
|
</div>
|
|
<el-tooltip
|
|
:content="t('profile.settings.referralTooltip')"
|
|
placement="top-end"
|
|
:disabled="finishedOrdersQuantity > 0"
|
|
>
|
|
<button
|
|
class="settings__button"
|
|
@click="copyReferral"
|
|
:disabled="finishedOrdersQuantity === 0"
|
|
>
|
|
<icon name="material-symbols:content-copy" size="20" />
|
|
{{ t('profile.settings.copyReferral') }}
|
|
</button>
|
|
</el-tooltip>
|
|
</div>
|
|
<div class="settings__main">
|
|
<p>{{ t('profile.settings.accountInfo') }}</p>
|
|
<forms-update />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import {usePageTitle} from '@composables/utils';
|
|
import { useDate } from '@composables/date';
|
|
import {useAvatarUpload} from '@composables/user';
|
|
|
|
const {t} = useI18n();
|
|
const userStore = useUserStore();
|
|
const { $appHelpers, $notify } = useNuxtApp();
|
|
|
|
const { uploadAvatar } = useAvatarUpload();
|
|
|
|
const cookieLocale = useCookie(
|
|
$appHelpers. COOKIES_LOCALE_KEY,
|
|
{
|
|
default: () => $appHelpers.DEFAULT_LOCALE,
|
|
path: '/'
|
|
}
|
|
);
|
|
|
|
const user = computed(() => userStore.user);
|
|
const finishedOrdersQuantity = computed(() => userStore.finishedOrdersQuantity);
|
|
const joinData = computed(() => {
|
|
return useDate(
|
|
user.value?.dateJoined, cookieLocale.value
|
|
);
|
|
});
|
|
|
|
const referralLink = computed(() => {
|
|
if (finishedOrdersQuantity.value > 0) {
|
|
return `https://${$appHelpers.APP_DOMAIN}/${$appHelpers.DEFAULT_LOCALE}/?referrer=` + user.value?.uuid;
|
|
} else {
|
|
return `https://${$appHelpers.APP_DOMAIN}/${$appHelpers.DEFAULT_LOCALE}/`;
|
|
}
|
|
});
|
|
|
|
const copyReferral = () => {
|
|
if (finishedOrdersQuantity.value > 0) {
|
|
navigator.clipboard.writeText(referralLink.value)
|
|
.then(() => {
|
|
$notify({
|
|
message: t('popup.success.referralCopy'),
|
|
type: 'success'
|
|
});
|
|
})
|
|
.catch(err => {
|
|
console.error(err);
|
|
});
|
|
}
|
|
};
|
|
|
|
const { setPageTitle } = usePageTitle();
|
|
|
|
setPageTitle(t('breadcrumbs.settings'));
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.settings {
|
|
background-color: $main;
|
|
width: 100%;
|
|
border: 1px solid $border;
|
|
border-radius: $default_border_radius;
|
|
height: fit-content;
|
|
|
|
&__top {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
justify-content: space-between;
|
|
gap: 25px;
|
|
padding: 24px 32px;
|
|
border-bottom: 1px solid $border;
|
|
|
|
&-left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 25px;
|
|
}
|
|
|
|
&-inner {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 5px;
|
|
|
|
& h2 {
|
|
color: $primary;
|
|
font-family: "Playfair Display", sans-serif;
|
|
font-size: 24px;
|
|
font-weight: 700;
|
|
}
|
|
|
|
& p {
|
|
color: $text;
|
|
font-size: 16px;
|
|
font-weight: 400;
|
|
}
|
|
}
|
|
}
|
|
|
|
&__avatar {
|
|
width: 80px;
|
|
height: 80px;
|
|
border-radius: 50%;
|
|
border: 2px solid $border;
|
|
background-color: rgba($primary, 0.2);
|
|
position: relative;
|
|
overflow: hidden;
|
|
|
|
@include hover {
|
|
.settings__avatar-inner {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
& label {
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 100%;
|
|
|
|
& span {
|
|
color: $disabled_secondary;
|
|
}
|
|
}
|
|
|
|
&-image {
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
}
|
|
|
|
&-inner {
|
|
position: absolute;
|
|
z-index: 1;
|
|
width: 100%;
|
|
height: 100%;
|
|
inset: 0;
|
|
display: grid;
|
|
place-items: center;
|
|
opacity: 0;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
|
|
& span {
|
|
color: $main !important;
|
|
}
|
|
}
|
|
|
|
& input {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
&__button {
|
|
cursor: pointer;
|
|
border-radius: $less_border_radius;
|
|
padding: 5px 15px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
|
|
color: $text;
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
|
|
@include hover {
|
|
background-color: $main_hover;
|
|
color: $secondary;
|
|
}
|
|
|
|
&:disabled {
|
|
cursor: not-allowed;
|
|
|
|
@include hover {
|
|
background-color: $main_hover;
|
|
color: $secondary;
|
|
}
|
|
}
|
|
}
|
|
|
|
&__main {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 25px;
|
|
padding: 24px 32px;
|
|
|
|
& p {
|
|
font-size: 24px;
|
|
font-weight: 600;
|
|
color: $primary_dark;
|
|
}
|
|
}
|
|
}
|
|
</style> |