update
This commit is contained in:
@@ -92,6 +92,7 @@
|
||||
))
|
||||
|
||||
const showStopUsingDialog = ref(false)
|
||||
|
||||
async function goTo (path: string) {
|
||||
if (path !== 'stop_using') {
|
||||
await router.push({ name: path })
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
{{$t('agreements__title')}}
|
||||
</template>
|
||||
<pn-scroll-list>
|
||||
<div class="flex column w100 q-pa-md q-gutter-y-md">
|
||||
<div>
|
||||
<div class="flex column w100 q-py-md q-px-lg q-gutter-y-sm text-caption">
|
||||
<div class="text-bold">
|
||||
<div v-if="route.query.type === 'update'">{{ $t('agreements__description_update') }}</div>
|
||||
<div>{{ $t('agreements__description') }}</div>
|
||||
</div>
|
||||
<div class="flex items-center no-wrap text-caption">
|
||||
<div class="flex items-center no-wrap">
|
||||
<q-checkbox v-model="agreement" val="1" class="q-pr-sm"/>
|
||||
<span>
|
||||
{{ $t('agreements__checkbox_agreement_terms') + ' ' }}
|
||||
@@ -21,7 +21,7 @@
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center no-wrap text-caption">
|
||||
<div class="flex items-center no-wrap">
|
||||
<q-checkbox v-model="agreement" val="2" class="q-pr-sm"/>
|
||||
<span>
|
||||
{{ $t('agreements__checkbox_agreement_consent') + ' ' }}
|
||||
@@ -43,7 +43,7 @@
|
||||
</div>
|
||||
</pn-scroll-list>
|
||||
<template #footer>
|
||||
<div class="flex no-wrap justify-center w100 q-gutter-x-md q-pb-md">
|
||||
<div class="flex no-wrap justify-center w100 q-gutter-x-md q-py-md">
|
||||
<q-btn
|
||||
flat
|
||||
color="negative"
|
||||
|
||||
@@ -4,14 +4,16 @@
|
||||
{{ $t('chat_card__title') }}
|
||||
</template>
|
||||
<template #footer>
|
||||
<q-btn
|
||||
rounded color="primary"
|
||||
class="w100 q-mt-md q-mb-xs"
|
||||
@click = "onSubmit"
|
||||
v-if="chat && chat.invite_link"
|
||||
>
|
||||
{{ $t("chat_card__go_chat") }}
|
||||
</q-btn>
|
||||
<div class="w100 q-pa-md">
|
||||
<q-btn
|
||||
rounded color="primary"
|
||||
class="w100"
|
||||
@click="onSubmit"
|
||||
v-if="chat"
|
||||
>
|
||||
{{ $t("chat_card__go_chat") }}
|
||||
</q-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<pn-scroll-list>
|
||||
@@ -118,18 +120,18 @@
|
||||
watch(() => chatsStore.isInit, initChat)
|
||||
|
||||
async function onSubmit () {
|
||||
if (chat.value && chat.value.invite_link) tg.openTelegramLink(chat.value.invite_link)
|
||||
if (chat.value) tg.openTelegramLink('https://t.me/c/' + chat.value.telegram_id + '/' + chat.value.message_id)
|
||||
if (chat.value) await chatsStore.getChatUsers(chat.value.id)
|
||||
}
|
||||
|
||||
const users = usersStore.getUsers
|
||||
const users = computed(() => usersStore.users)
|
||||
const companiesStore = useCompaniesStore()
|
||||
const { userSection } = useUserSection()
|
||||
|
||||
const chatUsers = computed(() => {
|
||||
if (!chat.value) return []
|
||||
const idSet = new Set(chat.value.users)
|
||||
const arr = users.filter(el => idSet.has(el.id))
|
||||
const arr = users.value.filter(el => idSet.has(el.id))
|
||||
return arr.map(el => ({
|
||||
...el,
|
||||
...userSection(el),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<company-block
|
||||
v-model="newCompany"
|
||||
title="company_add__title_card"
|
||||
btnText="company_add__btn"
|
||||
@update="addCompany"
|
||||
@@ -8,7 +7,6 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import companyBlock from 'components/companyBlock.vue'
|
||||
import { useCompaniesStore } from 'stores/companies'
|
||||
@@ -17,8 +15,6 @@
|
||||
const router = useRouter()
|
||||
const companiesStore = useCompaniesStore()
|
||||
|
||||
const newCompany = ref<CompanyParams>({} as CompanyParams)
|
||||
|
||||
async function addCompany(companyData: CompanyParams) {
|
||||
await companiesStore.add(companyData)
|
||||
router.go(-1)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<company-block
|
||||
v-if="company"
|
||||
v-model="company"
|
||||
:company
|
||||
title="company_edit__title_card"
|
||||
btnText="company_edit__btn"
|
||||
@update="updateCompany"
|
||||
@@ -12,6 +11,7 @@
|
||||
<q-icon name="star" class="q-pr-xs"/>
|
||||
{{ $t('company_edit__my_company') }}
|
||||
</div>
|
||||
|
||||
<div class="flex column">
|
||||
<div class="text-caption" align="center" style="white-space: pre-wrap;">
|
||||
{{ $t('company_edit__my_company_hint') }}
|
||||
@@ -26,45 +26,29 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import companyBlock from 'components/companyBlock.vue'
|
||||
import { useCompaniesStore } from 'stores/companies'
|
||||
import { parseIntString } from 'src/utils/helpers'
|
||||
import { parseIntString } from 'utils/helpers'
|
||||
import type { CompanyParams } from 'types/Company'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const companiesStore = useCompaniesStore()
|
||||
|
||||
const company = ref<CompanyParams | null>(null)
|
||||
const companyId = computed(() => parseIntString(route.params.companyId))
|
||||
|
||||
function initCompany() {
|
||||
if (companiesStore.isInit && companyId.value) {
|
||||
const foundCompany = companiesStore.companyById(companyId.value)
|
||||
if (foundCompany) {
|
||||
company.value = foundCompany as CompanyParams
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (companiesStore.isInit) initCompany()
|
||||
|
||||
watch(() => companiesStore.isInit, (isInit) => {
|
||||
if (isInit) initCompany()
|
||||
})
|
||||
const company = companyId.value && companiesStore.companyById(companyId.value) || {} as CompanyParams
|
||||
|
||||
async function goMyCompany () {
|
||||
await router.push({ name: 'your_company' })
|
||||
}
|
||||
|
||||
async function updateCompany (companyData: CompanyParams) {
|
||||
if (companyId.value) {
|
||||
await companiesStore.update(companyId.value, companyData)
|
||||
router.go(-1)
|
||||
}
|
||||
async function updateCompany (company: CompanyParams) {
|
||||
if (!companyId .value || !company) return
|
||||
await companiesStore.update(companyId.value, company)
|
||||
router.go(-1)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<pn-scroll-list>
|
||||
<template #card-body-header>
|
||||
<div class="q-ma-sm q-pa-sm bg-grey-11 flex no-wrap items-center" style="border-radius: var(--top-raduis);">
|
||||
<div class="q-ma-sm q-pa-sm bg-grey-11 flex no-wrap items-center" style="border-radius: var(--top-radius);">
|
||||
<q-icon name="mdi-information q-pr-xs" size="sm" color="primary"/>
|
||||
<span class="text-caption">
|
||||
{{ $t('mask__info_block')}}
|
||||
|
||||
@@ -238,6 +238,6 @@
|
||||
<style scoped>
|
||||
.login-card {
|
||||
opacity: 0.9 !important;
|
||||
border-radius: var(--top-raduis);
|
||||
border-radius: var(--top-radius);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<project-block
|
||||
v-model="newProject"
|
||||
title="project_create__title_card"
|
||||
btnText="project_create__btn"
|
||||
@update="addProject"
|
||||
@@ -8,7 +7,6 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import projectBlock from 'components/projectBlock.vue'
|
||||
import { useProjectsStore } from 'stores/projects'
|
||||
@@ -17,8 +15,6 @@
|
||||
const router = useRouter()
|
||||
const projectsStore = useProjectsStore()
|
||||
|
||||
const newProject = ref<ProjectParams>({} as ProjectParams)
|
||||
|
||||
async function addProject (projectData: ProjectParams) {
|
||||
const newDataProject = await projectsStore.add(projectData)
|
||||
await router.replace({ name: 'chats', params: { id: newDataProject.id }})
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<project-block
|
||||
v-if="project"
|
||||
v-model="project"
|
||||
:project
|
||||
title="project_edit__title_card"
|
||||
btnText="project_edit__btn"
|
||||
@update="updateProject"
|
||||
@@ -9,7 +8,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import projectBlock from 'components/projectBlock.vue'
|
||||
import { useProjectsStore } from 'stores/projects'
|
||||
@@ -18,27 +17,14 @@
|
||||
const router = useRouter()
|
||||
const projectsStore = useProjectsStore()
|
||||
|
||||
const project = ref<ProjectParams | null>(null)
|
||||
const projectId = computed(() => projectsStore.currentProjectId)
|
||||
|
||||
|
||||
if (projectsStore.isInit) {
|
||||
project.value = projectId.value
|
||||
? { ...projectsStore.projectById(projectId.value) } as ProjectParams
|
||||
: null
|
||||
}
|
||||
|
||||
watch(() => projectsStore.isInit, (isInit) => {
|
||||
if (isInit && projectId.value && !project.value) {
|
||||
project.value = { ...projectsStore.projectById(projectId.value) as ProjectParams }
|
||||
}
|
||||
})
|
||||
const project = projectId.value && projectsStore.projectById(projectId.value) || {} as ProjectParams
|
||||
|
||||
async function updateProject (projectData: ProjectParams) {
|
||||
if (projectId.value) {
|
||||
await projectsStore.update(projectId.value, projectData)
|
||||
router.go(-1)
|
||||
}
|
||||
if (!projectId .value || !project) return
|
||||
await projectsStore.update(projectId.value, projectData)
|
||||
router.go(-1)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -75,8 +75,8 @@
|
||||
const usersStore = useUsersStore()
|
||||
const companiesStore = useCompaniesStore()
|
||||
|
||||
const chatsQty = computed(() => chatsStore.getChats.length)
|
||||
const usersQty = computed(() => usersStore.getUsers.length)
|
||||
const chatsQty = computed(() => chatsStore.chats.length)
|
||||
const usersQty = computed(() => usersStore.users.length)
|
||||
const companiesQty = computed(() => companiesStore.getCompanies.length)
|
||||
|
||||
const tabs = ref([
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
v-if="projects.length!==0 || archiveProjects.length!==0"
|
||||
>
|
||||
<q-input
|
||||
v-if="projects.length!== 0"
|
||||
v-if="projects.length!==0"
|
||||
v-model="searchProject"
|
||||
clearable
|
||||
clear-icon="close"
|
||||
:placeholder="$t('projects__search')"
|
||||
dense
|
||||
dense filled
|
||||
class="col-grow q-px-md q-py-md"
|
||||
>
|
||||
<template #prepend>
|
||||
@@ -61,16 +61,16 @@
|
||||
/>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label lines="1" class="text-bold">{{ item.name }}</q-item-label>
|
||||
<q-item-label lines="1" class="text-bold">
|
||||
{{ item.name }}
|
||||
</q-item-label>
|
||||
<q-item-label
|
||||
caption lines="2"
|
||||
style="max-width: -webkit-fill-available; white-space: pre-line"
|
||||
>
|
||||
{{ item.description }}
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side top>
|
||||
<q-item-label lines="1" class="text-caption">
|
||||
<q-item-label lines="1" class="text-caption text-grey">
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center">
|
||||
<q-icon name="mdi-chat-outline"/>
|
||||
@@ -82,10 +82,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<q-item-label>
|
||||
<q-btn
|
||||
color="grey"
|
||||
size="sm"
|
||||
size="md"
|
||||
dense flat round
|
||||
icon="mdi-pencil"
|
||||
class="q-ml-sm"
|
||||
@@ -225,7 +227,7 @@
|
||||
|
||||
const router = useRouter()
|
||||
const projectsStore = useProjectsStore()
|
||||
const projects = projectsStore.getProjects
|
||||
const projects = computed(() => projectsStore.projects)
|
||||
const projectsInit = computed(() => projectsStore.isInit)
|
||||
|
||||
const searchProject = ref('')
|
||||
@@ -259,9 +261,9 @@
|
||||
}
|
||||
|
||||
const displayProjects = computed(() => {
|
||||
if (!searchProject.value || !(searchProject.value && searchProject.value.trim())) return projects
|
||||
if (!searchProject.value || !(searchProject.value && searchProject.value.trim())) return projects.value
|
||||
const searchChatValue = searchProject.value.trim().toLowerCase()
|
||||
const arrOut = projects
|
||||
const arrOut = projects.value
|
||||
.filter((el: Project) =>
|
||||
el.name.toLowerCase().includes(searchChatValue) ||
|
||||
el.description && el.description.toLowerCase().includes(searchProject.value)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<user-block
|
||||
v-if="user"
|
||||
v-model="user"
|
||||
:user
|
||||
title="user_edit__title_card"
|
||||
btnText="user_edit__btn"
|
||||
@update="updateUser"
|
||||
@@ -9,38 +8,25 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import userBlock from 'components/userBlock.vue'
|
||||
import { useUsersStore } from 'stores/users'
|
||||
import { parseIntString } from 'src/utils/helpers'
|
||||
import { parseIntString } from 'utils/helpers'
|
||||
import type { User } from 'types/User'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const usersStore = useUsersStore()
|
||||
|
||||
const user = ref<User | null>(null)
|
||||
const userId = computed(() => parseIntString(route.params.userId))
|
||||
|
||||
function initUser() {
|
||||
if (usersStore.isInit && userId.value) {
|
||||
const foundUser = usersStore.userById(userId.value)
|
||||
if (foundUser) {
|
||||
user.value = { ...foundUser } as User
|
||||
}
|
||||
}
|
||||
}
|
||||
const user = userId.value && usersStore.userById(userId.value) || {} as User
|
||||
|
||||
if (usersStore.isInit) initUser()
|
||||
|
||||
watch(() => usersStore.isInit, initUser)
|
||||
|
||||
async function updateUser (userData: User) {
|
||||
if (userId.value) {
|
||||
await usersStore.update(userId.value, userData)
|
||||
router.go(-1)
|
||||
}
|
||||
async function updateUser (user: User) {
|
||||
if (!userId .value || !user) return
|
||||
await usersStore.update(userId.value, user)
|
||||
router.go(-1)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -8,107 +8,177 @@
|
||||
</template>
|
||||
|
||||
<pn-scroll-list >
|
||||
<div class="q-px-md">
|
||||
<template #card-body-header>
|
||||
<div
|
||||
id="subscribe-current-balance"
|
||||
class="flex w100 q-px-md q-py-sm row"
|
||||
style="border-radius: var(--top-raduis); border: 1px solid var(--q-primary);"
|
||||
class="flex w100 q-px-md q-py-md row"
|
||||
>
|
||||
|
||||
<div class="flex w100 justify-between items-center no-wrap">
|
||||
<div class="flex no-wrap items-center text-h6 col-9">
|
||||
<div class="flex items-center text-grey">
|
||||
{{ $t('subscribe__current_plan') }}
|
||||
</div>
|
||||
|
||||
<div class="flex items-center column col-3">
|
||||
<div class="flex items-center column text-right">
|
||||
<span class="text-bold">
|
||||
{{ currentPlanData?.name }}
|
||||
</span>
|
||||
<span class="text-caption" style="line-height: 0.5em;">
|
||||
{{ $t('subscribe__plan_exp') }}
|
||||
{{ date.formatDate(currentPlanData.exp * 1000, 'DD.MM.YYYY') }}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex row w100 ow-wrap items-center text-caption q-pt-sm">
|
||||
<div class="col-9">{{ $t('subscribe__plan_active_chats') }}</div>
|
||||
<div class="col-3" align="center">
|
||||
<span class="text-brand2 text-bold q-pr-xs">{{ currentPlanData?.active_chats }}</span>
|
||||
<span class="text-grey">/{{ currentPlanData?.chatsQty }}</span>
|
||||
<div
|
||||
class="row w100 no-wrap items-center text-caption justify-between"
|
||||
v-if="currentPlanData.name !== 'TEST'"
|
||||
>
|
||||
<div class="text-grey text-no-wrap ellipsis">
|
||||
{{ $t('subscribe__plan_date') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="flex w100 justify-center text-grey q-pt-md q-pb-none">{{ $t('subscribe__plans')}}</div>
|
||||
<q-list separator>
|
||||
<q-item
|
||||
v-for="item in plans"
|
||||
:key="item.id"
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<q-radio v-model="newPlan" :val="item" v-if="item.name!=='TEST'"/>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<q-item-label class="text-bold">{{ item.name }}</q-item-label>
|
||||
<div class="flex no-wrap items-center text-caption">
|
||||
<span v-if="item.chatsQty" class="q-pr-xs">
|
||||
{{ $t('subscribe__chats_max') }}
|
||||
</span>
|
||||
<span v-if="item.chatsQty">
|
||||
{{ item.chatsQty }}
|
||||
</span>
|
||||
<q-icon v-else name="mdi-all-inclusive" size="sm"/>
|
||||
<span class="q-pl-xs">
|
||||
{{ $t('subscribe__chats')}}
|
||||
</span>
|
||||
</div>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<div v-if="item.price" class="flex column items-center">
|
||||
<div class="flex no-wrap items-center">
|
||||
<telegram-star color="gold" size="18px" class="q-mr-xs"/>
|
||||
<span class="text-h6">{{ formatNumber(item.price) }}</span>
|
||||
<span class="text-caption q-pl-xs">{{ $t('subscribe__per_month') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-bold">
|
||||
{{ $t('subscribe__free_tax') }}
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
<div class="flex w100 justify-center text-caption text-grey q-pt-sm text-center">
|
||||
{{ $t('subscribe__plans_description') }}
|
||||
</div>
|
||||
|
||||
<q-btn-group spread flat class="w100 q-py-sm">
|
||||
<q-btn
|
||||
v-for="period in periods"
|
||||
:key="period.id"
|
||||
:color="selectPeriod === period.value ? 'primary' : 'white'"
|
||||
:text-color="selectPeriod === period.value ? 'white' : 'primary'"
|
||||
@click="selectPeriod = period.value"
|
||||
no-caps
|
||||
>
|
||||
<div class="column items-center w100 self-end">
|
||||
<q-badge v-show="period.sale" color="red">{{ period.sale }}% off</q-badge>
|
||||
<span>{{ $t(period.name) }}</span>
|
||||
<span class="text-caption">({{ $t(period.name_in_days) }})</span>
|
||||
</div>
|
||||
</q-btn>
|
||||
</q-btn-group>
|
||||
|
||||
<div class="text-caption column text-grey">
|
||||
<span>{{ $t('subscribe__plans_period_notes') + ' ' }}</span>
|
||||
<span
|
||||
@click="router.push({ name: 'change_plan_rules' })"
|
||||
class="text-info cursor-pointer"
|
||||
>
|
||||
{{ $t('subscribe__plans_period_notes_more_info') }}
|
||||
<span class="text-no-wrap text-right">
|
||||
{{ date.formatDate(currentPlanData.exp * 1000, 'DD.MM.YYYY') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="row w100 no-wrap items-center text-caption text-grey justify-between">
|
||||
<div>
|
||||
{{ $t('subscribe__plan_active_chats') }}
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<span class="text-brand2 text-bold q-pr-xs">{{ currentPlanData?.active_chats }}</span>
|
||||
<span>/{{ currentPlanData?.chatsQty }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="w100 column items-center text-center text-grey q-px-md">
|
||||
{{ $t('subscribe__plans')}}
|
||||
<div class="text-caption">
|
||||
{{ $t('subscribe__plans_description') }}
|
||||
</div>
|
||||
</div>
|
||||
<q-list separator>
|
||||
<q-item
|
||||
v-for="item in plans"
|
||||
:key="item.id"
|
||||
clickable
|
||||
v-ripple
|
||||
tag="label"
|
||||
:disable="item.name === 'TEST' && currentPlanData.name !== 'TEST'"
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<q-radio
|
||||
v-model="newPlan"
|
||||
:val="item"
|
||||
:disable="item.name === 'TEST' && currentPlanData.name != 'TEST'"
|
||||
:keep-color="item.name === 'TEST'&& currentPlanData.name !== 'TEST'"
|
||||
:color="item.name === 'TEST' && currentPlanData.name !== 'TEST' ? 'grey-5' : ''"
|
||||
/>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
<div class="column">
|
||||
<span class="text-bold">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
<div class="flex no-wrap items-center text-caption" style="line-height: 1em;">
|
||||
<span v-if="item.chatsQty">
|
||||
{{ $t('subscribe__chats_max') + ' ' + item.chatsQty }}
|
||||
</span>
|
||||
<q-icon v-else name="mdi-all-inclusive" size="sm"/>
|
||||
<span class="q-pl-xs">
|
||||
{{ $t('subscribe__chats')}}
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
v-if="item.name === 'TEST' && currentPlanData.name !== 'TEST'"
|
||||
class="text-caption text-grey-7"
|
||||
>
|
||||
{{ $t('subscribe__TEST_via_support')}}
|
||||
</span>
|
||||
</div>
|
||||
</q-item-section>
|
||||
<q-item-section
|
||||
class="text-left"
|
||||
:style="{ width: `${maxWidthStarsSection}px` }"
|
||||
>
|
||||
<q-resize-observer @resize="updateMaxWidthStarsSection" />
|
||||
<div v-if="item.price" class="flex column justify-start">
|
||||
<div class="flex no-wrap items-center">
|
||||
<telegram-star color="gold" size="18px" class="q-mr-xs"/>
|
||||
<span class="text-h6">{{ formatNumber(item.price) }}</span>
|
||||
<span class="text-caption q-pl-xs">{{ $t('subscribe__per_month') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-bold self-center">
|
||||
{{ $t('subscribe__free_tax') }}
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-list>
|
||||
|
||||
<div class="q-px-md">
|
||||
<div class="w100 text-grey text-center q-pt-sm">
|
||||
{{ $t('subscribe__plans_interval') }}
|
||||
</div>
|
||||
|
||||
<q-btn-group spread flat class="w100 q-py-sm">
|
||||
<q-btn
|
||||
v-for="period in periods"
|
||||
:key="period.id"
|
||||
:outline="selectPeriod === period.value"
|
||||
@click="selectPeriod = period.value"
|
||||
:color="selectPeriod === period.value ? 'primary' : ''"
|
||||
no-caps dense
|
||||
>
|
||||
<div class="column items-center w100 self-end">
|
||||
|
||||
<span
|
||||
class="text-h6"
|
||||
:class="selectPeriod === period.value ? 'text-primary' : 'text-black'"
|
||||
>
|
||||
{{ $t(period.name) }}
|
||||
</span>
|
||||
<div
|
||||
class="row no-wrap w100 q-px-xs"
|
||||
:class="period.sale ? 'justify-between' : 'justify-center'"
|
||||
>
|
||||
<span
|
||||
class="text-caption text-grey"
|
||||
>
|
||||
{{ $t(period.name_in_days) }}
|
||||
</span>
|
||||
<q-badge v-show="period.sale" color="red">-{{ period.sale }}%</q-badge>
|
||||
</div>
|
||||
</div>
|
||||
</q-btn>
|
||||
</q-btn-group>
|
||||
|
||||
<div class="text-caption text-grey">
|
||||
<span>{{ $t('subscribe__plans_period_notes') + ' ' }}</span>
|
||||
<span
|
||||
@click="router.push({ name: 'change_plan_rules' })"
|
||||
class="text-info cursor-pointer"
|
||||
>
|
||||
{{ $t('subscribe__plans_period_notes_more_info') }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<q-input
|
||||
v-model="promocode"
|
||||
dense
|
||||
filled
|
||||
:label="$t('subscribe__promocode')"
|
||||
class="q-pt-md"
|
||||
>
|
||||
<template #append v-if="promocode !== ''">
|
||||
<q-btn
|
||||
round dense flat
|
||||
color="primary"
|
||||
icon="mdi-arrow-right-circle-outline"
|
||||
@click="sendPromocode"
|
||||
/>
|
||||
</template>
|
||||
</q-input>
|
||||
</div>
|
||||
</pn-scroll-list>
|
||||
</pn-page-card>
|
||||
@@ -121,12 +191,12 @@
|
||||
import { date } from 'quasar'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type { WebApp } from '@twa-dev/types'
|
||||
import { colors } from 'quasar';
|
||||
import { colors } from 'quasar'
|
||||
import { useQuasar } from 'quasar'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const tg = inject('tg') as WebApp
|
||||
tg.MainButton.show()
|
||||
|
||||
// @ts-expect-error: get hex text
|
||||
tg.MainButton.color = colors.getPaletteColor('primary')
|
||||
@@ -146,7 +216,7 @@
|
||||
|
||||
const selectPeriod = ref(periods[1]?.value)
|
||||
|
||||
const newPlan = ref(plans[1])
|
||||
const newPlan = ref(plans[0])
|
||||
|
||||
interface CurrentPlan {
|
||||
plan: string
|
||||
@@ -155,7 +225,7 @@
|
||||
}
|
||||
|
||||
const currentPlan = ref<CurrentPlan>({ // temp, this get from api
|
||||
plan: plans[0].val,
|
||||
plan: plans[1].val,
|
||||
active_chats: 20,
|
||||
exp: Date.now() / 1000 + 500000
|
||||
})
|
||||
@@ -186,12 +256,12 @@
|
||||
)
|
||||
const newDateExp = date.addToDate(Date.now(), { months: Number(selectPeriod.value) })
|
||||
|
||||
return t('subscribe__pay') + ' ⭐' + stars +
|
||||
return t(newPlan.value.id !== currentPlanData.value.id ? 'subscribe__pay' : 'subscribe__pay_renew') +
|
||||
' ⭐' + stars +
|
||||
' (' + t('subscribe__plan_exp') + ' ' +
|
||||
date.formatDate(newDateExp, 'DD.MM.YYYY') + ')'
|
||||
})
|
||||
|
||||
|
||||
function formatNumber (number: string | number) {
|
||||
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " ")
|
||||
}
|
||||
@@ -201,6 +271,43 @@
|
||||
watch(textBtn, () => tg.MainButton.setText(textBtn.value),
|
||||
{ immediate: true })
|
||||
|
||||
watch(newPlan, () =>
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||
{ newPlan.value.name === 'TEST' ? tg.MainButton.hide() : tg.MainButton.show() },
|
||||
{ immediate: true })
|
||||
|
||||
const maxWidthStarsSection = ref(0)
|
||||
|
||||
interface sizeParams {
|
||||
height: number,
|
||||
width: number
|
||||
}
|
||||
|
||||
function updateMaxWidthStarsSection (size: sizeParams) {
|
||||
if (size.width > maxWidthStarsSection.value) {
|
||||
maxWidthStarsSection.value = size.width
|
||||
}
|
||||
}
|
||||
|
||||
const promocode = ref('')
|
||||
|
||||
function sendPromocode () {
|
||||
promocode.value = ''
|
||||
showNotify('fail')
|
||||
}
|
||||
|
||||
const $q = useQuasar()
|
||||
|
||||
const showNotify = (message: 'success' | 'fail') => {
|
||||
$q.notify({
|
||||
message: t(message === 'success' ? 'subscribe__promocode_success' : 'subscribe__promocode_fail'),
|
||||
type: message === 'success' ? 'positive' : 'negative',
|
||||
position: 'bottom',
|
||||
timeout: 1000,
|
||||
multiLine: true
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
<div class="q-pa-none flex column col-grow no-scroll">
|
||||
<pn-scroll-list>
|
||||
<template #card-body-header>
|
||||
|
||||
<div class="flex row q-ma-md justify-between" v-if="chats.length !== 0">
|
||||
<q-input
|
||||
v-model="search"
|
||||
clearable
|
||||
clear-icon="close"
|
||||
:placeholder="$t('chats__search')"
|
||||
dense
|
||||
dense filled
|
||||
class="col-grow"
|
||||
v-if="chats.length !== 0"
|
||||
>
|
||||
@@ -52,18 +51,15 @@
|
||||
{{ item.description }}
|
||||
</q-item-label>
|
||||
<q-item-label caption lines="1">
|
||||
<div class = "flex justify-start items-center no-wrap">
|
||||
<div class="q-mr-sm flex items-center no-wrap">
|
||||
<q-icon name="mdi-account-multiple-outline" class="q-mr-xs"/>
|
||||
<span>{{ item.user_count }}</span>
|
||||
</div>
|
||||
<div class="q-mx-sm flex items-center no-wrap ellipsis" v-if="item.owner_id">
|
||||
<q-icon name="mdi-key" class="q-mr-xs"/>
|
||||
<span class="ellipsis">{{ usersStore.userNameById(item.owner_id) }} </span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</q-item-label>
|
||||
</q-item-section>
|
||||
<q-item-section side>
|
||||
<div class="flex items-center no-wrap text-caption">
|
||||
<q-icon name="mdi-account-outline"/>
|
||||
<span>{{ item.user_count }}</span>
|
||||
</div>
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</q-slide-item>
|
||||
</q-list>
|
||||
@@ -166,7 +162,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onActivated, onDeactivated, onBeforeUnmount, inject } from 'vue'
|
||||
import { useChatsStore } from 'stores/chats'
|
||||
import { useUsersStore } from 'stores/users'
|
||||
import type { WebApp } from '@twa-dev/types'
|
||||
import { useI18n } from "vue-i18n"
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
@@ -179,7 +174,6 @@
|
||||
const search = ref('')
|
||||
const showOverlay = ref<boolean>(false)
|
||||
const chatsStore = useChatsStore()
|
||||
const usersStore = useUsersStore()
|
||||
const showDialogDeleteChat = ref<boolean>(false)
|
||||
const deleteChatId = ref<number | undefined>(undefined)
|
||||
const currentSlideEvent = ref<SlideEvent | null>(null)
|
||||
@@ -192,7 +186,7 @@
|
||||
reset: () => void
|
||||
}
|
||||
|
||||
const chats = chatsStore.getChats
|
||||
const chats = computed(() => chatsStore.chats)
|
||||
const chatsInit = computed(() => chatsStore.isInit)
|
||||
|
||||
const fabMenu = [
|
||||
@@ -201,9 +195,9 @@
|
||||
]
|
||||
|
||||
const displayChats = computed(() => {
|
||||
if (!search.value || !(search.value && search.value.trim())) return chats
|
||||
if (!search.value || !(search.value && search.value.trim())) return chats.value
|
||||
const searchValue = search.value.trim().toLowerCase()
|
||||
const arrOut = chats
|
||||
const arrOut = chats.value
|
||||
.filter(el =>
|
||||
el.name.toLowerCase().includes(searchValue) ||
|
||||
el.description && el.description.toLowerCase().includes(searchValue)
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
<template>
|
||||
<div class="q-pa-none flex column col-grow no-scroll">
|
||||
<pn-scroll-list>
|
||||
<template #card-body-header>
|
||||
<div class="flex items-center justify-end q-pa-sm w100" v-if="companies.length !== 0">
|
||||
<q-btn
|
||||
:color="companies.length <= 2 ? 'grey-6' : 'primary'"
|
||||
flat
|
||||
no-caps
|
||||
@click="maskCompany"
|
||||
:disable="companies.length <= 2"
|
||||
class="q-pr-md"
|
||||
rounded
|
||||
>
|
||||
<q-icon
|
||||
left
|
||||
size="sm"
|
||||
name="mdi-domino-mask"
|
||||
class="q-mr-xs"
|
||||
/>
|
||||
<div>
|
||||
{{ $t('companies__mask')}}
|
||||
</div>
|
||||
</q-btn>
|
||||
</div>
|
||||
</template>
|
||||
<div class="flex items-center justify-end q-pa-sm w100" v-if="companies.length !== 0">
|
||||
<q-btn
|
||||
:color="companies.length <= 2 ? 'grey-6' : 'primary'"
|
||||
flat
|
||||
no-caps
|
||||
@click="maskCompany"
|
||||
:disable="companies.length <= 2"
|
||||
class="q-pr-md"
|
||||
rounded
|
||||
>
|
||||
<q-icon
|
||||
left
|
||||
size="sm"
|
||||
name="mdi-domino-mask"
|
||||
class="q-mr-xs"
|
||||
/>
|
||||
<div>
|
||||
{{ $t('companies__mask')}}
|
||||
</div>
|
||||
</q-btn>
|
||||
</div>
|
||||
|
||||
<q-list separator v-if="companies.length !== 0">
|
||||
<q-slide-item
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
id="project-info"
|
||||
v-if="project"
|
||||
:style="{ height: headerHeight + 'px', minHeight: '48px' }"
|
||||
class="flex row items-center justify-between no-wrap w100 q-gutter-x-sm"
|
||||
style="overflow: hidden; transition: height 0.3s ease-in-out; margin-left: 0"
|
||||
@@ -34,7 +35,7 @@
|
||||
size="lg"
|
||||
/>
|
||||
|
||||
<div class="flex column text-white fit">
|
||||
<div class="flex column text-white fit q-pl-sm">
|
||||
<div
|
||||
class="text-h6 q-pl-sm text-field"
|
||||
>
|
||||
@@ -85,18 +86,15 @@
|
||||
return currentProject
|
||||
? {
|
||||
name: currentProject.name,
|
||||
description: currentProject.description ?? '',
|
||||
logo: currentProject.logo ?? ''
|
||||
}
|
||||
: {
|
||||
name: '',
|
||||
description: '',
|
||||
logo: ''
|
||||
description: currentProject.description,
|
||||
logo: currentProject.logo
|
||||
}
|
||||
: null
|
||||
})
|
||||
|
||||
function toggleExpand () {
|
||||
expandProjectInfo.value = !expandProjectInfo.value
|
||||
if (project.value && (project.value.description || project.value.logo))
|
||||
expandProjectInfo.value = !expandProjectInfo.value
|
||||
}
|
||||
|
||||
async function toProjects () {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
clearable
|
||||
clear-icon="close"
|
||||
:placeholder="$t('users__search')"
|
||||
dense
|
||||
dense filled
|
||||
class="col-grow"
|
||||
>
|
||||
<template #prepend>
|
||||
@@ -254,7 +254,7 @@
|
||||
const usersStore = useUsersStore()
|
||||
const companiesStore = useCompaniesStore()
|
||||
|
||||
const users = usersStore.getUsers
|
||||
const users = computed(() => usersStore.users)
|
||||
const usersInit = computed(() => usersStore.isInit)
|
||||
|
||||
const blockUserId = ref<number | undefined>(undefined)
|
||||
@@ -263,7 +263,7 @@
|
||||
const closedByUserAction = ref(false)
|
||||
const { userSection } = useUserSection()
|
||||
|
||||
const mapUsers = computed(() => users.map(el => ({
|
||||
const mapUsers = computed(() => users.value.map(el => ({
|
||||
...el,
|
||||
...userSection(el),
|
||||
companyName: el.company_id && companiesStore.companyById(el.company_id)
|
||||
|
||||
Reference in New Issue
Block a user