fix_error
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-08-14 19:21:21 +03:00
parent ab94ad69a5
commit 04ea1f83c6
39 changed files with 2326 additions and 451 deletions

Binary file not shown.

1104
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,11 +15,11 @@
}, },
"dependencies": { "dependencies": {
"@quasar/cli": "^2.5.0", "@quasar/cli": "^2.5.0",
"@quasar/extras": "^1.16.4", "@quasar/extras": "^1.17.0",
"@quasar/vite-plugin": "^1.9.0", "@quasar/vite-plugin": "^1.10.0",
"axios": "^1.2.1", "axios": "^1.2.1",
"pinia": "^2.0.11", "pinia": "^2.0.11",
"quasar": "^2.18.1", "quasar": "^2.18.2",
"vue": "^3.4.18", "vue": "^3.4.18",
"vue-i18n": "^9.2.2", "vue-i18n": "^9.2.2",
"vue-router": "^4.0.12" "vue-router": "^4.0.12"
@@ -27,7 +27,8 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.14.0", "@eslint/js": "^9.14.0",
"@intlify/unplugin-vue-i18n": "^2.0.0", "@intlify/unplugin-vue-i18n": "^2.0.0",
"@quasar/app-vite": "^2.0.0", "@quasar/app-vite": "^2.3.0",
"@quasar/quasar-app-extension-qmarkdown": "^2.0.5",
"@twa-dev/types": "^8.0.2", "@twa-dev/types": "^8.0.2",
"@types/node": "^20.17.30", "@types/node": "^20.17.30",
"@types/telegram-web-app": "^7.10.1", "@types/telegram-web-app": "^7.10.1",

View File

@@ -1 +1,5 @@
{} {
"@quasar/qmarkdown": {
"import_md": true
}
}

View File

@@ -3,8 +3,18 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue' import { onMounted, inject } from 'vue'
import { useSettingsStore } from 'stores/settings' import { useSettingsStore } from 'stores/settings'
import { useRouter } from 'vue-router'
import type { WebApp } from '@twa-dev/types'
const router = useRouter()
const tg = inject('tg') as WebApp
tg.onEvent('settingsButtonClicked', async () => {
await router.push({ name: 'account' })
})
const settingsStore = useSettingsStore() const settingsStore = useSettingsStore()
onMounted(async () => { onMounted(async () => {

View File

@@ -0,0 +1,73 @@
*This document is an English translation of the original Russian-language "Consent to Personal Data Processing" (Version 1.01 dated 15.08.2025). In the event of any disputes, the original Russian version shall take precedence, particularly for matters resolved within the jurisdiction of the Russian Federation.*
# Consent to Personal Data Processing
###### Version 1.01 dated 15.08.2025
Pursuant to Federal Law No. 152-FZ dated 27.07.2006 "On Personal Data", acting freely, by my own will and in my own interest, and hereby confirming my legal capacity, I (hereinafter the **User**) grant my consent to Alexey Alexandrovich Martyshkin, Individual Entrepreneur (OGRNIP 318774600262084, INN 366316608346) (hereinafter the **Operator**) for the processing of my personal data under the following terms.
The following terms and definitions apply in this Consent:
**Bot** An account named @tgCrewBot with URL [https://t.me/tgCrewBot](https://t.me/tgCrewBot) in the Telegram messenger, programmatically managed by the Operator via API (Application Programming Interface). The Bot provides access to the Application and supports basic interaction via inline mode.
**Application** The tgCrew mini-app operating within the Telegram messenger environment as part of the Telegram Mini Apps (TMA) ecosystem, accessible through interaction with the Bot. While the Application utilizes Telegram's platform for functionality and distribution, it is exclusively developed and provided by the Operator. The Application is not a product of Telegram Messenger LLP, nor is it endorsed, supported, or legally affiliated with Telegram Messenger LLP.
**Personal Data (PD)** Any information relating to an identified or identifiable natural person (data subject) (per Federal Law No. 152-FZ, Chapter 1, Article 3, Clause 1).
**Administrator** A User of the Application who manages it through the Admin Panel.
**Administrator Account** An account used by the Administrator to authenticate access to the Admin Panel.
**Admin Panel** The Application interface for management functions, including:
- Connecting chats to the Application (see §1.12 Connected Chat)
- Adding supplementary User information
- Monitoring and processing Developer remuneration payments for Application usage.
**Connected Chat** A Telegram chat where the Bot has been added with necessary access rights. The Application only processes data from Connected Chats.
1. This Consent is specific, informed, conscious, and unambiguous.
2. The User consents to the Operator's processing of their Personal Data (using automated means), including:
a) Collection, recording, systematization, accumulation
b) Storage for the duration of the Administrator Account's existence, but no less than required by Russian law. Data is deleted upon Administrator Account closure, except where legally mandated (e.g., fraud prevention or court order execution)
c) Updating (modification, correction)
d) Retrieval, usage
e) Transfer (provision, access) to state authorities, courts, or law enforcement agencies exclusively upon official request under Russian law
f) Transfer (provision, access) to other Application Users within the same Connected Chat, limited to Application functionality requirements
g) Blocking, deletion, destruction
h) Other lawful processing activities under Russian legislation
3. Consent covers processing of the following User Personal Data, which may be:
- Provided directly by the User
- Entered by the Application Administrator (if User participates in a Connected Chat)
- Automatically collected by the Application:
a) Full name (surname, given name, patronymic)
b) Email address
c) Contact phone number
d) Employment details (organization, department, position/functional role)
e) Telegram account data: Display name (First/Last name), username, user ID, profile picture, Telegram client language settings; and for Administrators: Telegram Stars transaction data (user ID, amount, transaction ID, timestamp) transmitted automatically via Telegram API
f) Server interaction data (technical): Request IP address, request timestamp, requested URL, HTTP response code, response size (bytes), User-Agent, Referrer URL (if available)
4. Processing purposes:
a) Application authentication and identification (§§3b, 3e)
b) Technical support and request handling (§§3a-3e)
c) System notifications (for Administrators using email authentication) (§§3b, 3e)
d) Processing Telegram Stars transactions (for Administrators) (§§3b, 3e)
e) Generating contact directories within Connected Chats (§§3a-3e)
f) Ensuring proper Application functionality (§§3a-3e)
g) Technical maintenance and security (§§3f)
5. The User acknowledges that ticking the checkbox adjacent to the text: "✔ I consent to the processing of my personal data and accept the Privacy Policy" in the Application interface constitutes a simple electronic signature under Russian law, confirming:
- Review of this Consent
- Acceptance of the Operator's Privacy Policy available at: [https://tgcrew.ru/privacy-policy](https://tgcrew.ru/privacy-policy)
6. This Consent becomes effective upon completion of the action specified in §5 and remains valid until withdrawal.
7. Withdrawal is performed by:
- Selecting "Opt-Out from Application Usage" in Settings (User/Admin Panel)
- Confirming via "Confirm" in the dialog
Withdrawal results in cessation of processing and data destruction, except as stipulated in §8.
8. Post-withdrawal, the Operator retains the right to continue processing Personal Data without consent where grounds exist under Clauses 2-11 (Part 1, Article 6), Part 2 (Article 10), and Part 2 (Article 11) of Federal Law No. 152-FZ dated 27.07.2006 "On Personal Data".

View File

@@ -0,0 +1,63 @@
# Согласие на обработку персональных данных
###### Версия 1.01 от 15.08.2025
В соответствии с требованиями Федерального закона от 27.07.2006 № 152-ФЗ «О персональных данных», действуя свободно, своей волей и в своем интересе, а также подтверждая свою дееспособность, я (далее -- **Пользователь**) даю свое согласие индивидуальному предпринимателю Мартышкину Алексею Александровичу (ОГРНИП 318774600262084, ИНН 366316608346) (далее -- **Оператор**) на обработку своих персональных данных на изложенных ниже условиях.
В настоящем Согласии используются следующие термины и определения:
**Бот** -- аккаунт с именем @tgCrewBot и адресом [https://t.me/tgCrewBot](https://t.me/tgCrewBot) в мессенджере Telegram, управляемый программно Оператором через API (Application Programming Interface, программный интерфейс приложений). Бот предоставляет доступ к Приложению и может использоваться для базового взаимодействия из текстовой строки (inline-mode).
**Приложение** -- мини-приложение tgCrew, работающее в среде мессенджера Telegram как часть экосистемы Telegram Mini Apps (TMA) и доступное через взаимодействие с Ботом. Хотя Приложение использует платформу Telegram для своего функционирования и распространения, оно разработано и предоставляется исключительно Оператором. Приложение не является продуктом компании-разработчика мессенджера Telegram, не поддерживается ею, не одобрено ею и никак не связано с ней юридически или организационно.
**Персональные данные (или ПДн)** -- любая информация, относящаяся к прямо или косвенно определенному или определяемому физическому лицу (субъекту персональных данных) (согласно N152-ФЗ, Глава 1, Статья 3, п. 1).
**Администратор** -- Пользователь Приложения, который осуществляет его управление Приложением с помощью Панели администратора.
**Учетная запись Администратора** - учетная запись, с помощью которой Администратор осуществляет аутентификацию для доступа к Панели администратора.
**Панель администратора** -- интерфейс Приложения для управления Приложением, в том числе осуществления следующих функций:
- подключение чатов к Приложению (см. п. 1.12 Подключенный чат);
- внесение дополнительных информационных данных для Пользователей;
- контроль и осуществление выплат вознаграждения Разработчику за использование Приложения.
**Подключенный чат** (к Приложению) -- чат в Telegram, в который добавлен Бот с необходимыми правами доступа. В Приложении доступна информация только из Подключенных чатов.
1. Настоящее согласие является конкретным, информированным, сознательным и однозначным.
2. Согласие дано Оператору на обработку персональных данных Пользователя (с использованием средств автоматизации), включающую следующие действия:
а) Сбор, запись, систематизация, накопление.
б) Хранение в течение всего срока существования Учетной записи Администратора, но не менее срока, требуемого законодательством РФ. Данные удаляются при закрытии Учетной записи Администратора, за исключением случаев, предусмотренных законом (например, для предотвращения мошенничества или исполнения судебных решений).
в) Уточнение (обновление, изменение).
г) Извлечение, использование.
д) Передача (предоставление, доступ) государственным органам, судам или правоохранительным структурам исключительно по официальному запросу в рамках законодательства РФ.
е) Передачу (предоставление, доступ) другим Пользователям Приложения, имеющим общий Подключенный чат с Пользователем, в объёме, необходимом для функциональности Приложения.
ж) Блокирование, удаление, уничтожение.
з) Осуществление иных действий, предусмотренных законодательством РФ.
3. Согласие дается на обработку следующих персональных данных Пользователя, которые могут быть предоставлены самим Пользователем и (или) внесены Администратором Приложения (если Пользователь является участником Подключенного чата) и (или) автоматически собраны Приложением:
а) Фамилия, имя, отчество.
б) Адрес электронной почты.
в) Контактный телефон.
г) Сведения о месте работы (наименование организации, структурное подразделение, должность и/или функциональная роль).
д) Данные учетной записи в мессенджере Telegram: имя пользователя (Name, вкл. в себя - First name и Last name), псевдоним (Username), идентификатор пользователя (ID), изображение профиля (аватар), языковые настройки клиента Telegram, а также, если Пользователь является Администратором, данные транзакций Telegram Stars (идентификатор пользователя, количество Telegram Stars, идентификатор транзакции, временная метка операции), которые автоматически передаются через API Telegram.
е) Данные о взаимодействии с серверами Приложения (технические данные): IP-адрес с которого осуществляется запрос, дата и время получения запроса сервером Приложения, запрошенный URL, HTTP-код ответа сервера Приложения, размер ответа в байтах, User-Agent (информация о браузере и операционной системе клиента), Referrer (URL страницы, с которой был сделан запрос, если доступно).
4. Обработка персональных данных осуществляется в следующих целях:
а) Идентификация и аутентификация в Приложении (пп. 3б и 3д).
б) Предоставление технической поддержки и обработка обращений (пп. 3а-3д).
в) Отправка системных уведомлений если Пользователь является Администратором Приложения и использует электронную почту для аутентификации (пп. 3б и 3д).
г) Обработка платежных транзакций через Telegram Stars, в случае если Пользователь является Администратором Приложения (пп. 3б и 3д).
д) Формирование адресной книги контактов в рамках Подключенных чатов (пп. 3а-3д).
е) Обеспечение корректной работы функционала Приложения (пп. 3а-3д).
ж) Технические: профилактика технических сбоев и обеспечение безопасности (пп. 3е).
5. Я выражаю согласие на квалификацию проставления символа «V» (галочки) в чек-боксе интерфейса Приложения рядом с текстом: «Я даю Согласие на обработку своих персональных данных и принимаю условия Политики конфиденциальности» в качестве простой электронной подписи, удостоверяющей факт ознакомления и согласия с условиями настоящего Согласия и Политики конфиденциальности Оператора, размещенной в Приложении и в открытом доступе в сети Интернет по адресу: [https://tgcrew.ru/privacy-policy]( https://tgcrew.ru/privacy-policy).
6. Настоящее согласие вступает в силу с момента его предоставления путем совершения действий, указанных в пункте 5 настоящего Согласия, и действует до момента отзыва.
7. Отзыв настоящего Согласия осуществляется путем нажатия на кнопку «Отказ от использования приложения» и последующим нажатием в открывшемся диалоге кнопки «Подтвердить». Кнопка «Отказ от использования приложения» размещена в разделе Настройки (как для Пользовательской части, так и для Панели Администратора). Отзыв Согласия влечет прекращение обработки персональных данных и их уничтожение, за исключением случаев, предусмотренных пунктом 8 настоящего Согласия.
8. В случае отзыва настоящего согласия Оператор вправе продолжить обработку персональных данных Пользователя без его согласия при наличии оснований, предусмотренных пунктами 2-11 части 1 статьи 6, частью 2 статьи 10 и частью 2 статьи 11 Федерального закона от 27.07.2006 № 152-ФЗ «О персональных данных».

View File

@@ -0,0 +1,162 @@
*This document is an English adaptation of the Privacy Policy originally drafted in Russian. In the event of any disputes subject to resolution in courts of the Russian Federation, the Russian-language version shall prevail.*
# Privacy Policy
###### Version 1.01 dated 15.08.2025
This Privacy Policy describes the scope of data (including personal data) collection from Users of the Application by the Developer, explains the purposes of such collection, and outlines processing methods.
## 1. Terms and Definitions
1.1. **Bot** The Telegram account "@tgCrewBot" ([https://t.me/tgCrewBot](https://t.me/tgCrewBot)), programmatically managed by the Developer via Telegrams API. The Bot provides access to the Application and supports basic inline-mode interaction.
1.2. **Application** The Telegram Mini App (TMA) "tgCrew", operating within Telegrams ecosystem and accessible via the Bot. Though hosted on Telegrams platform, the Application is developed and provided solely by the Developer. It is not a product of, endorsed by, or legally affiliated with Telegram FZ-LLC. Access requires acceptance of the Terms of Use and this Privacy Policy.
1.3. **Website** The official site [https://tgcrew.ru](https://tgcrew.ru), hosting Application documentation and information.
1.4. **Terms of Use** The current version available at [https://tgcrew.ru/terms-of-use](https://tgcrew.ru/terms-of-use) and within the Application. In case of discrepancies, the in-Application version prevails. Contractual relations commence upon in-Application acceptance.
1.5. **Privacy Policy** This document governing the collection, storage, and processing of User data (including personal data). An integral annex to the Terms of Use. The current version is at [https://tgcrew.ru/privacy-policy](https://tgcrew.ru/privacy-policy) and in the Application. In-Application information prevails in conflicts. Consent is obtained via in-Application acceptance.
1.6. **Developer** Individual Entrepreneur Martyshkin Alexey Alexandrovich (OGRNIP 318774600262084, INN 366316608346, Russian Federation).
1.7. **User** An individual, legal entity, or authorized representative accepting the Terms of Use and Privacy Policy within the Application.
1.8. **Administrator** A User managing the Application via the Admin Panel.
1.9. **Administrator Account** Authentication credentials for Admin Panel access.
1.10. **Chat Participant** A member of a Connected Chat who may not be an Application User.
1.11. **Admin Panel** The Application interface for:
- Connecting chats to the Application (see §1.12);
- Adding supplemental User data;
- Managing Developer remuneration payments.
1.12. **Connected Chat** A Telegram chat where the Bot is added with necessary permissions. Only data from Connected Chats is processed.
1.13. **Application Use** User actions to view/utilize Application functionality via online interfaces.
1.14. **Developers Representatives** Persons engaged by the Developer for Application development/support.
1.15. **Personal Data (PD)** Any information relating to an identified/identifiable natural person (Federal Law No. 152-FZ, Art. 3.1).
1.16. **Personal Data Processing** Any operation(s) performed with PD, including collection, recording, storage, alteration, retrieval, use, transfer, anonymization, blocking, or destruction (Federal Law No. 152-FZ, Art. 3.3).
1.17. **Operator** A legal/natural person organizing and/or processing PD, defining processing purposes and scope (Federal Law No. 152-FZ, Art. 3.2).
1.18. **Automated PD Processing** PD processing via computer technology (Federal Law No. 152-FZ, Art. 3.4).
1.19. **PD Provision** Disclosure of PD to specific person(s) (Federal Law No. 152-FZ, Art. 3.6).
1.20. **Cross-Border PD Transfer** Transfer of PD to foreign authorities/entities (Federal Law No. 152-FZ, Art. 3.11).
1.21. **PD Destruction** Actions rendering PD irrecoverable (Federal Law No. 152-FZ, Art. 3.8).
## 2. General Provisions
2.1. This Policy governs solely the Developer-User relationship. It does not replace Telegrams Privacy Policy.
2.2. This Policy complies with:
- Federal Law No. 152-FZ "On Personal Data" (27.07.2006);
- Section "4. Privacy" of Telegrams "Bot Platform Developer Terms of Service".
2.3. The Developer acts as the **Operator** for PD processing.
## 3. Acceptance of this Policy
3.1. Acceptance occurs by ticking "✔ I consent to the processing of my personal data and accept the Privacy Policy" within the Application.
3.2. Application Use implies consent to data collection from Connected Chats (§§4.2-4.4).
3.3. Non-acceptance requires immediate cessation of Application Use.
## 4. Data Collection and Processing
4.1. Essential User data is required for Application access.
4.2. **Collected Personal Data**:
4.2.1. Automatically collected via Telegram API:
- Username, Telegram ID, profile picture, language settings, Telegram Stars transaction data (Administrators only).
- Technical data: IP address, request timestamp, requested URL, HTTP status, response size, User-Agent, Referrer.
4.2.2. **Administrator-provided**:
- Email (if used for authentication).
4.2.3. **Administrator-supplied Chat Participant data** (via Admin Panel):
- Full name, phone number, email, employment details.
*The Developer ensures lawful processing but assumes no liability for data accuracy. Administrators must secure legal grounds for PD submission. Data is visible only to Users sharing a Connected Chat. Users may request data correction/deletion from Administrators.*
4.2.4. **User-provided data** (e.g., support requests):
- Full name, phone number, email, employment details.
4.3. **Cookies**: Only HttpOnly cookies (mitigating XSS risks) are used.
4.4. **Chat Monitoring**: The Bot tracks events in Connected Chats (message/file changes). Relevant data is stored.
4.5. **User-Input Data Storage**: Project/company/task/meeting details.
4.6. **Non-Storage**: Chat/files are stored exclusively within Telegram.
4.7. **No Additional Collection**: Only data specified in §4.2 is collected.
## 5. Data Collection Purposes
5.1. Purposes include:
- User identification/authentication (§4.2.1a, 4.2.2);
- Technical support (§4.2.1, 4.2.2, 4.2.4);
- Administrator notifications (§4.2.1a, 4.2.2);
- Telegram Stars transactions (§4.2.1a);
- Connected Chat contact management (§4.2.1a, 4.2.3);
- Application functionality (§4.2, 4.4);
- Security/technical maintenance (§4.2.1b, 4.3).
5.2. Data is used solely for these purposes, unless required by Russian law or compatible purposes. New purposes trigger User notification.
5.3. PD processing is **automated**.
## 6. Data Security
6.1. Technical/organizational measures ensure PD confidentiality, integrity, and protection against loss/theft/unauthorized access.
6.2. Measures include SSL encryption for data transmission.
6.3. Only authorized Developer personnel access PD. Representatives have no PD access. Security protocols are periodically reviewed.
## 7. Data Transfer
7.1. No third-party transfers except to courts/state bodies when legally mandated.
7.2. The Developer will not sell/exchange PD without explicit consent.
7.3. **Data Localization**: All servers reside in Russia. **No cross-border transfers**.
## 8. User Rights
8.1. PD subject rights include:
- **Access**: PD copies provided within 30 calendar days.
- **Rectification**: Correction via Application functionality, Administrator request, or direct contact.
- **Erasure**: Deletion requests honored where legally permissible. Account closure triggers automatic deletion, except where retention is legally required (e.g., fraud prevention, legal obligations).
- **Consent Withdrawal**: Withdrawal does not affect pre-withdrawal processing lawfulness.
8.2. Rights are not absolute and may be balanced against the Developers legal obligations/legitimate interests. Refusals include justification.
## 9. Data Retention
9.1. PD is retained only as necessary for collection purposes.
9.2. Standard retention period: Duration of the Administrator Account.
9.3. Post-account closure retention occurs only if mandated by Russian law.
9.4. Extended retention applies for legal compliance, fraud prevention, or dispute resolution.
## 10. Policy Amendments
10.1. The Developer may revise this Policy without prior notice. The revision date will be updated.
10.2. Users should periodically review the Policy on the Website or in the Application.
10.3. Continued Application Use after revisions implies acceptance.
## 11. Miscellaneous
11.1. Queries regarding Policy interpretation: Contact the Developer at [a-mart@ya.ru](mailto:a-mart@ya.ru).
11.2. Contact details (§12) may be used for Policy-related matters.
## 12. Developer Contact Information
**Individual Entrepreneur Martyshkin Alexey Alexandrovich**
Legal address: 111394, Russia, Moscow, Perovskaya St., 66, Bldg. 3, Apt. 187
OGRNIP: 318774600262084
INN: 366316608346
Phone: +7 (926) 339-04-25
Email: [a-mart@ya.ru](mailto:a-mart@ya.ru)

View File

@@ -0,0 +1,172 @@
# Политика конфиденциальности
###### Версия 1.01 от 15.08.2025
В настоящей Политике конфиденциальности Разработчик предоставляет информацию о пределах сбора данных (в том числе персональных) Пользователей в Приложении, объясняет причины их сбора и способы их использования.
## 1. Термины и определения
1.1. **Бот** -- аккаунт с именем @tgCrewBot и адресом [https://t.me/tgCrewBot](https://t.me/tgCrewBot) в мессенджере Telegram, управляемый программно Разработчиком через API (Application Programming Interface, программный интерфейс приложений). Бот предоставляет доступ к Приложению и может использоваться для базового взаимодействия из текстовой строки (inline-mode).
1.2. **Приложение** -- мини-приложение tgCrew, работающее в среде мессенджера Telegram как часть экосистемы Telegram Mini Apps (TMA) и доступное через взаимодействие с Ботом. Хотя Приложение использует платформу Telegram для своего функционирования и распространения, оно разработано и предоставляется исключительно Разработчиком. Приложение не является продуктом компании-разработчика мессенджера Telegram, не поддерживается ею, не одобрено ею и никак не связано с ней юридически или организационно. Функционал Приложения доступен только после принятия Пользовательского соглашения и Политики конфиденциальности.
1.3. **Сайт** -- веб-сайт, расположенный по адресу: [https://tgcrew.ru](https://tgcrew.ru), на котором размещается информация о Приложении и его документация.
1.4. **Пользовательское соглашение** -- документ, актуальная (текущая) версия которого размещается на Сайте по ссылке [https://tgcrew.ru/terms-of-use](https://tgcrew.ru/terms-of-use), а также в Приложении. Если между текстом Пользовательского соглашения, размещенным на Сайте, и текстом, доступным в Приложении, возникают расхождения, то приоритет имеет текст, доступный в Приложении. Договорные отношения между Разработчиком и Пользователем возникают только после принятия Пользовательского соглашения внутри Приложения.
1.5. **Политика конфиденциальности** -- настоящий документ, регулирующий порядок сбора, хранения и обработки данных (в том числе персональных) Пользователя, введенных им в ходе процедуры регистрации, использования Приложения, а также иных данных. Является неотъемлемым приложением к Пользовательскому соглашению. Актуальная (текущая) версия Политики конфиденциальности размещается на Сайте по ссылке [https://tgcrew.ru/privacy-policy](https://tgcrew.ru/privacy-policy), а также в Приложении. Если между информацией о Политике конфиденциальности, размещенной на Сайте, и информацией, доступной в Приложении, возникают расхождения, то приоритет имеет информация, доступная в Приложении. Согласие на обработку данных в рамках Политики конфиденциальности предоставляется Пользователем внутри Приложения.
1.6. **Разработчик** -- индивидуальный предприниматель Мартышкин Алексей Александрович (ИП Мартышкин А.А.), ОГРНИП 318774600262084, ИНН 366316608346 (Российская Федерация).
1.7. **Пользователь** -- физическое лицо, индивидуальный предприниматель, юридическое лицо или их уполномоченный представитель, принявшее условия Пользовательского соглашения и Политики конфиденциальности путем их явного подтверждения внутри интерфейса Приложения.
1.8. **Администратор** -- Пользователь Приложения, который осуществляет его управление Приложением с помощью Панели администратора.
1.9. **Учетная запись Администратора** - учетная запись, с помощью которой Администратор осуществляет аутентификацию для доступа к Панели администратора.
1.10. **Участник чата** -- участник Подключенного чата, который может не являться Пользователем Приложения.
1.11. **Панель администратора** -- интерфейс Приложения для управления Приложением, в том числе осуществления следующих функций:
- подключение чатов к Приложению (см. п. 1.12 Подключенный чат);
- внесение дополнительных информационных данных для Пользователей;
- контроль и осуществление выплат вознаграждения Разработчику за использование Приложения.
1.12. **Подключенный чат** (к Приложению) -- чат в Telegram, в который добавлен Бот с необходимыми правами доступа. В Приложении доступна информация только из Подключенных чатов.
1.13. **Использование Приложения** -- совершение Пользователем действий по просмотру и (или) использованию доступного функционала Приложения посредством воспроизводимых онлайн-интерфейсов на экране устройства Пользователя.
1.14. **Представители Разработчика** -- круг лиц, привлекаемых Разработчиком в рамках разработки и поддержки Приложения, действующие от имени и (или) по поручению Разработчика.
1.15. **Персональные данные (или ПДн)** -- любая информация, относящаяся к прямо или косвенно определенному или определяемому физическому лицу (субъекту персональных данных) (согласно N152-ФЗ, Глава 1, Статья 3, п. 1).
1.16. **Обработка персональных данных** -- любое действие (операция) или совокупность действий (операций), совершаемых с использованием средств автоматизации или без использования таких средств с персональными данными, включая сбор, запись, систематизацию, накопление, хранение, уточнение (обновление, изменение), извлечение, использование, передачу (распространение, предоставление, доступ), обезличивание, блокирование, удаление, уничтожение персональных данных (согласно N152-ФЗ, Глава 1, Статья 3, п. 3).
1.17. **Оператор** -- государственный орган, муниципальный орган, юридическое или физическое лицо, самостоятельно или совместно с другими лицами организующие и (или) осуществляющие обработку персональных данных, а также определяющие цели обработки персональных данных, состав персональных данных, подлежащих обработке, действия (операции), совершаемые с персональными данными (согласно N152-ФЗ, Глава 1, Статья 3, п. 2).
1.18. **Автоматизированная обработка персональных данных** -- обработка персональных данных с помощью средств вычислительной техники (согласно N152-ФЗ, Глава 1, Статья 3, п. 4).
1.19. **Предоставление персональных данных** -- действия, направленные на раскрытие персональных данных определенному лицу или определенному кругу лиц (согласно N152-ФЗ, Глава 1, Статья 3, п. 6).
1.20. **Трансграничная передача персональных данных** -- передача персональных данных на территорию иностранного государства органу власти иностранного государства, иностранному физическому лицу или иностранному юридическому лицу (согласно N152-ФЗ, Глава 1, Статья 3, п. 11).
1.21. **Уничтожение персональных данных** -- действия, в результате которых становится невозможным восстановить содержание персональных данных в информационной системе персональных данных и (или) в результате которых уничтожаются материальные носители персональных данных (согласно N152-ФЗ, Глава 1, Статья 3, п. 8).
## 2. Общие положения
2.1. Настоящая Политика конфиденциальности регулирует исключительно отношения между Разработчиком и Пользователем. Она не может регулировать отношения между мессенджером Telegram (далее - Telegram) и его пользователями и не заменяет Политику конфиденциальности Telegram.
2.2. Настоящая Политика конфиденциальности составлена согласно требованиям:
- Федерального закона от 27.07.2006. № 152-ФЗ «О персональных данных».
- Требованиям раздела «4. Privacy» документа «Telegram Bot Platform Developer Terms of Service» от компании Telegram FZ-LLC (разработчик мессенджера Telegram).
2.3. Разработчик выступает в роли Оператора при Обработке персональных данных Пользователей Приложения.
## 3. Прием условий настоящей Политики конфиденциальности
3.1. Свидетельством полного и безоговорочного принятия условий настоящей Политики конфиденциальности (акцептом), является осуществление процедуры принятия Политики конфиденциальности путем проставления символа «V» (галочки) в чек-боксе интерфейса Приложения рядом с текстом: «Я даю Согласие на обработку своих персональных данных и принимаю условия Политики конфиденциальности» на соответствующих экранах в Приложении.
3.2. Использование Приложения означает согласие Пользователя на сбор и обработку информации из Подключенных чатов в соответствии с Политикой конфиденциальности (см. пп. 4.2-4.4).
3.3. В случае, если Пользователь не согласен с условиями Политики конфиденциальности, он обязан немедленно покинуть Приложение и не начинать/прекратить Использование Приложения.
## 4. Сбор и обработка данных
4.1. Чтобы предоставить Пользователю доступ к Приложению, ему необходимо предоставить Разработчику доступ к важной информации о себе.
4.2. Персональные данные, собираемые Приложением
4.2.1. Приложение в автоматическом режиме собирает следующие данные Пользователей, которые могут быть определены как Персональные данные:
а) Данные предоставляемые Telegram через API: имя пользователя (Name, вкл. в себя First name и Last name), псевдоним (Username), идентификатор пользователя (ID), изображение профиля (аватар), языковые настройки клиента Telegram, данные транзакций Telegram Stars (только для Администратора).
б) Данные о взаимодействии Пользователя с серверами Приложения (технические данные): IP-адрес с которого осуществляется запрос, дата и время получения запроса сервером Приложения, запрошенный URL, HTTP-код ответа сервера Приложения, размер ответа в байтах, User-Agent (информация о браузере и операционной системе клиента), Referrer (URL страницы, с которой был сделан запрос, если доступно).
4.2.2. Администратор предоставляет:
- адрес электронной почты, если используется аутентификация в Приложении с ее использованием.
4.2.3. Администратор в Панели администратора может указать данные для каждого участника Подключенного чата, которые могут быть определены как Персональные данные:
- фамилия, имя, отчество;
- контактный телефон;
- адрес электронной почты;
- сведения о месте работы (наименование организации, структурное подразделение, должность и (или) функциональная роль).
Разработчик не несет ответственности за корректность и точность указанных данных, но как Оператор обеспечивает законность их обработки. Администратор обязан обеспечить наличие правовых оснований для предоставления персональных данных Пользователей в соответствии с применимым законодательством (в случае указания реальных данных).
Предоставление указанных данных о Пользователе в Приложении, которые могут быть определены как Персональные данные, другим Пользователям, осуществляется только для Пользователей, имеющих общий Подключенный чат. Принимая данную Политику конфиденциальности, Пользователь согласен с таким предоставлением его данных. При необходимости, пользователь может обратиться к Администратору для удаления или изменения выше указанных данных.
4.2.4. Пользователи при обращении к Разработчику (например, при запросе в техническую поддержку Приложения) вправе предоставить любые следующие данные, которые могут быть определены как Персональные данные:
- фамилия, имя, отчество;
- контактный телефон;
- адрес электронной почты;
- сведения о месте работы (наименование организации, структурное подразделение, должность и (или) функциональная роль).
4.3. Приложение при создании и поддержания http-соединения использует HttpOnly cookie-файлы, которые не доступны из JavaScript через свойства Document.cookie API и используются для снижения риска XSS (Cross-Site Scripting - «межсайтовый скриптинг»). Другие cookie-файлы не устанавливаются и не используются.
4.4. Приложение с помощью Бота отслеживает события в Подключенных чатах (такие как добавление/изменение/удаление сообщений, добавление/удаление файлов и т.п.). При необходимости для реализации функционала Приложения эти изменения фиксируются в базе данных Приложения.
4.5. Приложение хранит данные, которые Пользователи вводят в Приложении, в том числе:
- данные проектов (имя, описание, логотип),
- данные компаний (название, адрес, контактный телефон, веб-сайт и т.п.),
- данные задач и совещаний (описание, дата и время и т.п.).
4.6. Разработчик не хранит на своих серверах файлы из чатов, задач и совещаний (хранение осуществляется внутри Telegram).
4.7. Приложение не собирает на стороне Пользователя никакую дополнительную информацию, которая может быть определена как Персональные данные, кроме той, что указана в п. 4.2, а также не осуществляет анализ информации, которая доступна ему в чатах.
## 5. Цели сбора данных
5.1. Сбор данных осуществляется со следующими целями:
- Идентификация и аутентификация Пользователей в Приложении (пп. 4.2.1а и 4.2.2).
- Предоставление технической поддержки и обработка обращений (пп. 4.2.1, 4.2.2 и 4.2.4).
- Отправка системных уведомлений Администратору (пп. 4.2.1а и 4.2.2).
- Обработка платежных транзакций через Telegram Stars (пп. 4.2.1а).
- Формирование адресной книги контактов в рамках Подключенных чатов (пп. 4.2.1а и 4.2.3).
- Обеспечение корректной работы функционала Приложения (пп. 4.2 и 4.4).
- Технические: направленные на профилактику технических сбоев и обеспечение безопасности (пп. 4.2.1б и 4.3).
5.2. Разработчик обязуется собирать и использовать данные Пользователя только для вышеуказанных целей, за исключением случаев, когда сбор и использование данных необходим для других целей, совместимых с первоначальной целью сбора данных, или когда это предусмотрено законодательством Российской Федерации. Если Разработчику потребуется использовать данные Пользователя для других целей, не упомянутых выше, Разработчик обязан уведомить Пользователя и разъяснить правовые основания для такого сбора.
5.3. Обработка персональных данных Пользователей осуществляется Разработчиком с использованием средств автоматизации.
## 6. Защита данных
6.1. Разработчик внедрил ряд технических, организационных и административных мер для обеспечения конфиденциальности, целостности, доступности и неприкосновенности и защиты Ваших данных (в том числе ПДн) от потери, кражи, несанкционированного доступа, неправомерного использования, изменения или уничтожения.
6.2. Эти меры включают, помимо прочего, внедрение современных технологий безопасности: технологию Secure Sockets Layered (SSL) для обеспечения полного шифрования данных Пользователя и их безопасной передачи через Интернет.
6.3. Только уполномоченный персонал Разработчика имеет доступ к Персональным данным Пользователей, и этот персонал обязан относиться к Персональным данным как к конфиденциальным. Представители Разработчика не получают доступа к данным Пользователей (в том числе персональным). Меры безопасности могут периодически пересматриваться в соответствии с юридическими и техническими изменениями.
## 7. Передача данных
7.1. Разработчик не осуществляет передачу данных (в том числе ПДн), полученных от Пользователей, третьим лицам, кроме случаев предоставления данных судам и(или) государственным органам и(или) правоохранительным органам в случаях, когда это требуется законами и нормативными актами.
7.2. Разработчик гарантирует Пользователю, что не будет продавать, обменивать или передавать ваши данные (в том числе ПДн) третьим лицам без вашего явного согласия.
7.3. Все сервера Приложения находятся на территории Российской Федерации. Трансграничная передача персональных данных не осуществляется.
## 8. Права пользователей
8.1. Основные права Пользователя как субъекта Персональных данных включают:
- **Право на доступ к Персональным данным.** Пользователь может запросить у Разработчика предоставление ему копии своих Персональных данных, к которым у Разработчика есть доступ. Разработчик предоставляет такую информацию Пользователю в разумные сроки (не более 30 календарных дней).
- **Право на исправление Персональных данных.** Пользователь может потребовать от Разработчика исправить или обновить любые свои Персональные данные. Пользователь может сделать это с помощью соответствующей функциональности Приложения, запросив Администратора или связавшись с нами напрямую. Разработчик оставляет за собой право отказывать в персональной помощи в случаях, когда исправление Персональных данных доступно через функциональность Приложения или с помощью Администратора.
- **Право на удаление Персональных данных.** Пользователь может потребовать от Разработчика удалить свои Персональные данные, с учетом применимого законодательства. В некоторых случаях Приложение автоматически удалит Персональные данные при закрытии Учетной записи в Приложении. Если Пользователь закрывает свою Учетную запись, Разработчик не будет использовать его Персональные данные для каких-либо дальнейших целей, а также передавать их третьим лицам, за исключением случаев, предусмотренных законом. Разработчик не всегда сможет выполнить запрос Пользователя на удаление по конкретным юридическим причинам, о которых будет сообщено Пользователю при наличии соответствующих оснований (например, если обработка необходима для достижения целей, предусмотренных законом, для исполнения судебного акта, для осуществления прав и законных интересов Разработчика или третьих лиц).
- **Право на отзыв согласия.** В той мере, в какой обработка Персональных данных Пользователя основана исключительно на его согласии, Пользователь может отозвать свое согласие в любое время. Это не повлияет на правомерность любой обработки, которая была осуществлена до отзыва. Любые действия по обработке, не основанные на согласии Пользователя, останутся незатронутыми.
8.2. Ни одно из прав не является абсолютным, что означает, что они, как правило, должны быть взвешены против собственных юридических обязательств Разработчика, а также его законных интересов и интересов третьих лиц. Если будет принято решение отклонить запрос Пользователя, то Разработчик проинформирует его об этом вместе с причинами такого решения.
## 9. Хранение данных
9.1. Разработчик хранит данные (в том числе ПДн) Пользователя не дольше, чем это необходимо для цели их сбора или обработки (с последующим удалением).
9.2. Как правило, Разработчик хранит данные (в том числе ПДн) на протяжении всего срока существования Учетной записи Администратора.
9.3. В случаях, предусмотренных применимым законодательством, Персональные данные могут храниться после закрытия Учетной записи Администратора в течение периода, установленного такими законами.
9.4. Разработчик может хранить данные (в том числе ПДн) Пользователя в течение более длительного периода, если это требуется соответствующими законами и нормативными актами. Разработчик может сохранять некоторые данные (в том числе ПДн) Пользователя после закрытия Учетной записи Администратора для предотвращения мошенничества, обеспечивая, чтобы лица, пытающиеся совершить мошенничество, не могли избежать обнаружения, просто закрыв учетную запись и открыв новую, а также для выполнения юридических обязательств Разработчика.
## 10. Изменения в Политике конфиденциальности
10.1. Настоящая Политика конфиденциальности может быть пересмотрена, обновлена и(или) изменена в любое время без предварительного уведомления по усмотрению Разработчика. Если такие изменения будут внесены, дата обновления настоящей Политики конфиденциальности будет отображена на первой странице Политики конфиденциальности.
10.2. Пользователю рекомендуется самостоятельно и регулярно отслеживать изменения Политики конфиденциальности, путем ознакомления с актуальной версией Политики конфиденциальности на Сайте или в Приложении.
10.3. После публикации обновленной версии Политики конфиденциальности дальнейшее использование Приложения считается принятием условий обновленной Политики конфиденциальности.
## 11. Прочие положения
11.1. Если какие-либо положения настоящей Политики конфиденциальности остались неясными, Разработчик готов разъяснить ее положения. Для этого свяжитесь с Разработчиком по адресу электронной почты [a-mart@ya.ru](mailto:a-mart@ya.ru).
11.2. Пользователь может использовать контактные данные, приведенные в разделе 12, по любой причине, предусмотренной настоящей Политикой.
## 12. Контактная информация и реквизиты Разработчика
Индивидуальный предприниматель Мартышкин Алексей Александрович
Юридический адрес: 111394, Российская Федерация, г. Москва, ул. Перовская, д. 66, к.3, кв. 187
ОГРНИП 318774600262084
ИНН 366316608346
Телефон: +7 (926)339-04-25
Электронная почта: [a-mart@ya.ru](mailto:a-mart@ya.ru)

View File

@@ -0,0 +1,153 @@
*This document is an English adaptation of the Terms of Use originally drafted in Russian. In the event of any disputes subject to resolution in courts of the Russian Federation, the Russian-language version shall prevail.*
# Terms of Use
###### Version 1.01 dated 15.08.2025
This Terms of Use constitutes a Public Offer by Individual Entrepreneur Martyshkin A.A. (IE Martyshkin A.A.) addressed to any individual, individual entrepreneur, and/or legal entity under the terms specified herein.
## 1. Terms and Definitions
1.1. **Bot** — An account named @tgCrewBot located at [https://t.me/tgCrewBot](https://t.me/tgCrewBot) within the Telegram messenger, programmatically managed by the Developer via API (Application Programming Interface). The Bot provides access to the Application and supports basic interaction via inline mode.
1.2. **Application** — The tgCrew mini-application operating within the Telegram messenger as part of the Telegram Mini Apps (TMA) ecosystem, accessible via interaction with the Bot. While the Application utilizes Telegrams platform for operation and distribution, it is developed and provided solely by the Developer. The Application is not a product of Telegram Messenger LLP, is not endorsed, supported, or affiliated with it legally or organizationally. Functionality requires acceptance of this Terms of Use and the Privacy Policy.
1.3. **Website** — The web platform located at: [https://tgcrew.ru](https://tgcrew.ru), hosting information and documentation about the Application.
1.4. **Terms of Use** — This document, the current version of which is published on the Website at [https://tgcrew.ru/terms-of-use](https://tgcrew.ru/terms-of-use) and within the Application. In case of discrepancies between the Website and Application versions, the Application version prevails. Contractual relations commence upon acceptance within the Application.
1.5. **Privacy Policy** — The document governing the collection, storage, and processing of User data (including personal data) entered during registration, application use, or otherwise. It is an integral annex to this Terms of Use. The current version resides at [https://tgcrew.ru/privacy-policy](https://tgcrew.ru/privacy-policy) and within the Application. The Application version prevails in case of discrepancies. Consent under the Privacy Policy is granted within the Application.
1.6. **Developer** — Individual Entrepreneur Martyshkin Alexey Alexandrovich (IE Martyshkin A.A.), OGRNIP (Primary State Registration Number of Individual Entrepreneur) 318774600262084, TIN (Taxpayer Identification Number) 366316608346 (Russian Federation).
1.7. **User** — An individual, individual entrepreneur, legal entity, or authorized representative accepting this Terms of Use and Privacy Policy via explicit confirmation within the Application interface.
1.8. **Administrator** — A User managing the Application via the Admin Panel.
1.9. **Administrator Account** — The account used by the Administrator to authenticate and access the Admin Panel.
1.10. **Chat Participant** — A participant in a Connected Chat who may not be an Application User.
1.11. **Admin Panel** — The Application interface for management functions, including:
- Connecting chats to the Application (see 1.12 Connected Chat);
- Adding supplementary User information;
- Managing payments to the Developer.
1.12. **Connected Chat** — A Telegram chat where the Bot has been added with necessary permissions. The Application only processes data from Connected Chats.
1.13. **Application Use** — Actions performed by the User to view and/or utilize Application functionality via online interfaces rendered on the Users device.
1.14. **Developers Representatives** — Parties engaged by the Developer for development and support, acting on behalf of the Developer.
1.15. **Tariff Plan** — The Developers offering to the Administrator for Application use, including functionality and remuneration. Tariffs are described on the Website and in the Application. Tariffs may be modified by the Developer no more than once per 3 (three) months. The Application version prevails in case of discrepancies.
## 2. Subject Matter of the Terms of Use
2.1. This Terms of Use grants the User the right to use the Application under the terms herein.
2.2. Use within Telegram may require User account registration.
## 3. User Warranties and Representations
3.1. By accepting these Terms, the User warrants:
3.1.1. They are at least 18 years old (or the age of majority in their jurisdiction) and capable of fulfilling obligations under these Terms.
3.1.2. Application use is permitted under their jurisdictions laws. If prohibited, use must cease immediately.
3.1.3. They have read and fully understand these Terms and the Privacy Policy.
3.1.4. Use will comply with applicable laws.
3.1.5. They will take reasonable steps to secure their Telegram account. Loss of Administrator Account access requires immediate notification to the Developer at [a-mart@ya.ru](mailto:a-mart@ya.ru) and cooperation to resolve the issue.
3.1.6. If warranties (3.1.1-3.1.5) are breached, the User must cease use immediately and notify the Developer. The Developer may suspend or terminate access.
3.2. Use is prohibited if warranties are not met.
## 4. Acceptance of Offer
4.1. Full acceptance is evidenced by checking "✔ I accept the Terms of Use" within the Application interface.
4.2. Use implies consent to data processing from Connected Chats per the Privacy Policy.
4.3. Actions within the Application constitute legally binding conclusive acts. Logs from the Developers database serve as primary evidence of such actions in disputes.
4.4. Non-acceptance requires immediate cessation of use.
## 5. Term
5.1. Effective upon acceptance until obligations are fulfilled or termination occurs.
5.2. Access termination ends these Terms.
## 6. Application Description
6.1. Provided "AS IS" and "AS AVAILABLE". No warranties (fitness, availability, defect-free operation) are provided.
6.2. Allows Administrators via the Admin Panel to consolidate data from Telegram chats by adding the Bot.
6.3. Participants can track chat data (files, tasks, meetings) via the Application.
6.4. Users access data only from their participating Connected Chats.
6.5. Bot access requires explicit addition by a chat admin with appropriate rights.
## 7. Remuneration Procedure
7.1. Payments are made solely via the Admin Panel per the Tariff Plan.
7.2. Telegram Stars are the exclusive payment method.
7.3. Administrators transfer Stars to the Applications internal balance. Daily deductions occur per Tariff (~00:00 UTC+3).
7.4. Unused Stars refund:
- Only upon termination of use.
- Requires email notification to [a-mart@ya.ru](mailto:a-mart@ya.ru) with Administrator ID.
- Processed within 30 calendar days post-Developer confirmation.
- Not applicable if balance <100 Stars or technically infeasible.
7.5. Chat Participants use the Application free of charge.
7.6. Suspected incorrect deductions must be reported immediately to [a-mart@ya.ru](mailto:a-mart@ya.ru). Developer will investigate within 10 business days.
7.7. Developer bears no responsibility for Telegram Stars payment system operations.
7.8. Telegram Stars are not stored funds; solely for Developer remuneration.
7.9. Insufficient balance may suspend functionality until replenishment (notification via Bot/email).
## 8. Liability
8.1. Developer may conduct maintenance, potentially causing downtime. Advance notice (24h+) for extended planned outages.
8.2. Developer may modify/restrict functionality at any time (except Tariffs (1.15) and material Terms changes (13.1)).
8.3. Developer and Representatives bear no liability for losses (direct, indirect, consequential) arising from use.
8.4. User is solely responsible for Telegram account security. Actions under their account are deemed theirs.
8.5. User Prohibitions:
- Reverse engineer, decompile, disassemble the Application.
- Create derivative works.
- Remove/hide Developers intellectual property notices.
8.6. No malware introduction, scraping, or unauthorized automated access.
8.7. No unauthorized access attempts or DDoS attacks. Violations result in immediate termination and legal reporting.
8.8. No illegal, obscene, offensive, or rights-infringing use.
8.9. User responsible for own IT setup.
8.10. Developer may suspend/terminate access for suspected Terms breaches or reputational harm.
8.11. Access may be terminated for Privacy Policy or legal violations.
8.12. For terminations under 8.10-8.11, Developer may retain unused Stars as penalty/compensation if permitted by Russian law.
8.13. Developer not liable for content processed/displayed via the Application or User actions in chats. Users bear content legality responsibility.
8.14. Developer may terminate the Application entirely, notifying Administrators 30+ days in advance. Unused Stars will be refunded per 7.4.
## 9. Intellectual Property
9.1. Developer grants a limited, non-exclusive, non-transferable, revocable license to use the Application. All rights not expressly granted are reserved. License terminates automatically upon Terms termination.
9.2. Global intellectual property rights belong solely to the Developer. Rights are licensed, not sold.
## 10. Force Majeure
10.1. Parties exempt from liability for force majeure (natural disasters, war, government actions, telecom failures, etc.).
10.2. Performance deadlines extended for the force majeure duration (max 30 calendar days).
10.3. Force majeure exceeding 30 days triggers negotiations for alternatives or termination without damages.
## 11. Severability
11.1. Invalidity of any provision does not affect the validity of others. Invalid provisions shall be replaced by valid ones reflecting the original intent as closely as possible.
11.2. Invalidity does not affect Sections 7 (Remuneration), 9 (IP), 12 (Governing Law), 15.4 (Indemnification), and 15.6 (No Waiver).
## 12. Governing Law and Dispute Resolution
12.1. Governed by and construed under the laws of the Russian Federation. Unforeseen matters resolved under Russian law.
12.2. Disputes resolved via negotiation/email (mandatory pre-trial claim procedure). Unresolved disputes after 30 calendar days subject to litigation in Moscow, Russia.
## 13. Amendments
13.1. Developer may amend these Terms by publishing the revised version on the Website/Application. Changes effective the day after publication. User must review amendments regularly.
13.2. User may reject amendments, implying cessation of use.
## 14. Assignment
14.1. Developer may assign rights/obligations without User consent. User may not assign without Developers prior written consent.
14.2. Developers assignment does not release it from pre-assignment liabilities unless otherwise agreed or required by law.
## 15. Final Provisions
15.1. Russian language version prevails over translations.
15.2. Notices to Developer: [a-mart@ya.ru](mailto:a-mart@ya.ru) or methods specified in App/Website. Developer notices deemed received 1 day after publishing/sending.
15.3. Personal data processed per the Privacy Policy (integral annex).
15.4. User indemnifies Developer for losses (including legal costs) arising from Users breach of Terms, law, or third-party rights.
15.5. Entire Terms supersedes prior arrangements.
15.6. Developers inaction on breach does not waive future rights.
15.7. No agency, partnership, joint venture, or franchise relationship created.
15.8. Compatibility with all devices/OS/Telegram versions not guaranteed.
## 16. Developer Contact & Details
**Individual Entrepreneur Martyshkin Alexey Alexandrovich**
Legal Address: 111394, Russian Federation, Moscow, Perovskaya St., 66, Bldg. 3, Apt. 187
OGRNIP 318774600262084
TIN 366316608346
Phone: +7 (926) 339-04-25
Email: [a-mart@ya.ru](mailto:a-mart@ya.ru)

View File

@@ -0,0 +1,197 @@
# Пользовательское соглашение
###### Версия 1.01 от 15.08.2025
Текст настоящего Пользовательского соглашения является публичной офертой ИП Мартышкин А.А. и адресован любому физическому лицу, индивидуальному предпринимателю и (или) юридическому лицу на изложенных в нём условиях.
## 1. Термины и определения
1.1. **Бот** -- аккаунт с именем @tgCrewBot и адресом [https://t.me/tgCrewBot](https://t.me/tgCrewBot) в мессенджере Telegram, управляемый программно Разработчиком через API (Application Programming Interface, программный интерфейс приложений). Бот предоставляет доступ к Приложению и может использоваться для базового взаимодействия из текстовой строки (inline-mode).
1.2. **Приложение** -- мини-приложение tgCrew, работающее в среде мессенджера Telegram как часть экосистемы Telegram Mini Apps (TMA) и доступное через взаимодействие с Ботом. Хотя Приложение использует платформу Telegram для своего функционирования и распространения, оно разработано и предоставляется исключительно Разработчиком. Приложение не является продуктом компании-разработчика мессенджера Telegram, не поддерживается ею, не одобрено ею и никак не связано с ней юридически или организационно. Функционал Приложения доступен только после принятия Пользовательского соглашения и Политики конфиденциальности.
1.3. **Сайт** -- веб-сайт, расположенный по адресу: [https://tgcrew.ru](https://tgcrew.ru), на котором размещается информация о Приложении и его документация.
1.4. **Пользовательское соглашение** -- настоящий документ, актуальная (текущая) версия которого размещается на Сайте по ссылке [https://tgcrew.ru/terms-of-use](https://tgcrew.ru/terms-of-use), а также в Приложении. Если между текстом Пользовательского соглашения, размещенным на Сайте, и текстом, доступным в Приложении, возникают расхождения, то приоритет имеет текст, доступный в Приложении. Договорные отношения между Разработчиком и Пользователем возникают только после принятия Пользовательского соглашения внутри Приложения.
1.5. **Политика конфиденциальности** -- документ, регулирующий порядок сбора, хранения и обработки данных (в том числе персональных) Пользователя, введенных им в ходе процедуры регистрации, использования Приложения, а также иных данных. Является неотъемлемым приложением к Пользовательскому соглашению. Актуальная (текущая) версия Политики конфиденциальности размещается на Сайте по ссылке [https://tgcrew.ru/privacy-policy](https://tgcrew.ru/privacy-policy), а также в Приложении. Если между информацией о Политике конфиденциальности, размещенной на Сайте, и информацией, доступной в Приложении, возникают расхождения, то приоритет имеет информация, доступная в Приложении. Согласие на обработку данных в рамках Политики конфиденциальности предоставляется Пользователем внутри Приложения.
1.6. **Разработчик** -- индивидуальный предприниматель Мартышкин Алексей Александрович (ИП Мартышкин А.А.), ОГРНИП 318774600262084, ИНН 366316608346 (Российская Федерация).
1.7. **Пользователь** -- физическое лицо, индивидуальный предприниматель, юридическое лицо или их уполномоченный представитель, принявшее условия Пользовательского соглашения и Политики конфиденциальности путем их явного подтверждения внутри интерфейса Приложения.
1.8. **Администратор** -- Пользователь Приложения, который осуществляет его управление Приложением с помощью Панели администратора.
1.9. **Учетная запись Администратора** - учетная запись, с помощью которой Администратор осуществляет аутентификацию для доступа к Панели администратора.
1.10. **Участник чата** -- участник Подключенного чата, который может не являться Пользователем Приложения.
1.11. **Панель администратора** -- интерфейс Приложения для управления Приложением, в том числе осуществления следующих функций:
- подключение чатов к Приложению (см. п. 1.12 Подключенный чат);
- внесение дополнительных информационных данных для Пользователей;
- контроль и осуществление выплат вознаграждения Разработчику за использование Приложения.
1.12. **Подключенный чат** (к Приложению) -- чат в Telegram, в который добавлен Бот с необходимыми правами доступа. В Приложении доступна информация только из Подключенных чатов.
1.13. **Использование Приложения** -- совершение Пользователем действий по просмотру и (или) использованию доступного функционала Приложения посредством воспроизводимых онлайн-интерфейсов на экране устройства Пользователя.
1.14. **Представители Разработчика** -- круг лиц, привлекаемых Разработчиком в рамках разработки и поддержки Приложения, действующие от имени и (или) по поручению Разработчика.
1.15. **Тариф** -- предложение, сформированное Разработчиком для Администратора по использованию Приложения, которое включает, в том числе: функциональность и вознаграждение Разработчика за использование Приложения. Описание Тарифа/Тарифов доступны на Сайте и в Приложении. Тарифы могут изменяться Разработчиком не чаще одного раза в 3 (Три) месяца. Если между информацией о Тарифе/Тарифах, размещенной на Сайте, и информацией, доступной в Приложении, возникают расхождения, то приоритет имеет информация, доступная в Приложении.
## 2. Предмет Пользовательского соглашения
2.1. Настоящее Пользовательское соглашение предоставляет Пользователю право использовать Приложение на условиях, определенных в данном документе.
2.2. Для использования Приложения в мессенджере Telegram (далее - Telegram) от Пользователя может потребоваться регистрация учетной записи.
## 3. Гарантии и заверения Пользователя
3.1. Принимая данное Пользовательское соглашение, Пользователь гарантирует:
3.1.1. Достиг возраста 18 лет (а также возраста совершеннолетия в своей стране проживания) и что не существует обстоятельств, препятствующих Пользователю в полном объеме исполнять свои обязательства по данному Пользовательскому соглашению.
3.1.2. Законодательство страны проживания Пользователя разрешает использование Приложения. В случае запрета Пользователь обязан немедленно прекратить использование.
3.1.3. Полностью ознакомился с текстом Пользовательского соглашения и Политикой конфиденциальности, понимает их условия и принимает их в полном объеме.
3.1.4. Использование Приложения будет осуществляться в рамках применимого законодательства.
3.1.5. Пользователь принимает разумные меры для сохранения контроля над своей учетной записью Telegram. В случае утраты доступа к учетной записи, используемой для управления Приложением в роли Администратора, Пользователь обязан незамедлительно уведомить Разработчика по электронной почте [a-mart@ya.ru](mailto:a-mart@ya.ru) и сотрудничать для разрешения ситуации.
3.1.6. При прекращении соответствия гарантиям (пп. 3.1.1-3.1.5) Пользователь обязан немедленно прекратить использование Приложения и уведомить Разработчика. В этом случае Разработчик вправе приостановить или прекратить доступ Пользователя к Приложению (путем блокировки Учетной записи Администратора).
3.2. Пользователь не вправе использовать Приложение, если не соответствует гарантиям в п. 3.1.
## 4. Прием оферты
4.1. Свидетельством полного и безоговорочного принятия условий настоящего Пользовательского соглашения (акцептом), является осуществление процедуры принятия Пользовательского соглашения путем проставления символа «V» (галочки) в чек-боксе интерфейса Приложения рядом с текстом: «Я принимаю Пользовательское соглашение» на соответствующих экранах в Приложении.
4.2. Использование Приложения означает согласие Пользователя на сбор и обработку информации из Подключенных чатов в соответствии с Политикой конфиденциальности.
4.3. Все действия, совершенные в рамках функциональности Приложения Пользователем, признаются Разработчиком и таким Пользователем как конклюдентные действия, порождающие соответствующие юридические последствия. При этом Пользователь соглашается с тем, что основным доказательством совершения или несовершения определенного действия с использованием интерфейсов Приложения может служить для Разработчика предоставление выписки из своей базы данных о наличии информации, зафиксированной путем логирования (сохранения истории) действий такого лица (или иным аналогичным способом). В случае спора такая информация предоставляется в выбранной Разработчиком форме и признается исчерпывающим доказательством действий, указанных в настоящем пункте.
4.4. В случае, если Пользователь не согласен с условиями Пользовательского соглашения, он обязан немедленно покинуть Приложение и не начинать/прекратить Использование Приложения.
## 5. Срок действия Пользовательского соглашения
5.1. Пользовательское соглашение действует с момента акцепта Пользователем до полного исполнения обязательств Сторонами или прекращения этого соглашения.
5.2. Досрочное прекращение доступа к Приложению влечет прекращение действия Пользовательского соглашения.
## 6. Описание Приложения
6.1. Пользователь признает и соглашается с тем, что функциональность Приложения предоставляется "КАК ЕСТЬ" и "ПО МЕРЕ ДОСТУПНОСТИ" ("AS IS" и "AS AVAILABLE"), без каких-либо гарантий, включая гарантии в отношении коммерческой ценности, пригодности для конкретных целей, постоянной доступности и т.п. Разработчик не гарантирует безошибочную работу Приложения, соответствие его функциональности ожиданиям Пользователя, а также отсутствие дефектов, вирусов или иных вредоносных компонентов.
6.2. Приложение позволяет Администратору с помощью Панели администратора объединять информацию из разных чатов Telegram путем добавления Бота в эти чаты. После добавления Бота (с предварительно настроенными в Приложении необходимыми правами) в чат, Бот получает доступ ко всем сообщениям в этом чате и сводит полученную информацию в базу данных Приложения.
6.3. Участники Подключенных чатов могут с помощью графического интерфейса Приложения отслеживать информацию из этих чатов, такую как: загруженные файлы, поставленные задачи и назначенные совещания, а также видеть перечень подключенных чатов.
6.4. Пользователю в Приложении доступна информация только из тех чатов, участником которых он является и которые были подключены к Приложению Администратором.
6.5. Доступ Бота к сообщениям в чате осуществляется исключительно после его явного добавления в чат участником, обладающим необходимыми правами администратора чата в Telegram (владелец чата или администратор с соответствующими правами), и предоставления Боту этих прав администратора чата.
## 7. Порядок и способы выплаты вознаграждения
7.1. Выплата вознаграждения Разработчику производится только в Панели администратора Приложения, согласно Тарифу.
7.2. Единственным способом выплаты вознаграждения Разработчику является использование внутренней валюты Telegram (Telegram Stars).
7.3. Администратор перечисляет (переводит) Telegram Stars на внутренний баланс в Приложении, откуда происходит выплата (списание) вознаграждения Разработчику на ежедневной основе, согласно Тарифу (ориентировочное время списания 00:00 UTC +3:00, Европа/Москва).
7.4. Возврат неизрасходованных Telegram Stars с баланса Приложения:
- Возможен только при прекращении использования Приложения (отказ от Пользовательского соглашения).
- Требует уведомления Разработчика по электронной почте [a-mart@ya.ru](mailto:a-mart@ya.ru) с указанием идентификатора учетной записи Telegram Администратора.
- Осуществляется Разработчиком в течение 30 календарных дней с момента подтверждения Разработчиком возможности и размера возврата.
- Не производится, если остаток менее 100 Telegram Stars или возврат технически невозможен со стороны платежной системы Telegram.
7.5. Участники чата осуществляют Использование Приложения бесплатно.
7.6. По вопросам предположительно некорректных или ошибочных списаний Администратор должен незамедлительно сообщить Разработчику по электронной почте [a-mart@ya.ru](mailto:a-mart@ya.ru). Разработчик обязуется рассмотреть обращение в разумный срок, обычно не превышающий 10 (Десять) рабочих дней.
7.7. Разработчик не контролирует и не несет ответственности за работу платежной системы Telegram Stars.
7.8. Разработчик не предоставляет услуги хранения средств. Telegram Stars, переведенные на баланс Приложения, не являются банковским вкладом или иным финансовым инструментом и предназначены исключительно для оплаты вознаграждения Разработчику в соответствии с Тарифом.
7.9. В случае недостаточного баланса Telegram Stars на счету Администратора в Приложении для ежедневного списания, функционал Приложения может быть частично приостановлен до пополнения баланса. Администратор будет уведомлен о необходимости пополнения баланса через сообщение от Бота или по электронной почте (в зависимости от способа аутентификации).
## 8. Ответственность сторон
8.1. Разработчик вправе проводить технические и иные работы, направленные на улучшение и (или) изменение функциональности Приложения. В период проведения таких работ Приложение может быть недоступно полностью или частично. Разработчик по возможности будет уведомлять Пользователей о длительных плановых работах через Приложение и (или) Сайт не менее чем за 24 часа.
8.2. Разработчик оставляет за собой право изменять, модифицировать или вводить дополнительные ограничения по своему усмотрению в любое время без предварительного уведомления, за исключением изменений Тарифов (п. 1.1) и существенных изменений условий настоящего Пользовательского соглашения (п. 13.1).
8.3. Разработчик и его Представители не несут ответственности за любые убытки (прямые, косвенные, упущенная выгода), возникшие в связи с использованием Приложения.
8.4. Пользователь самостоятельно несет ответственность за сохранность и конфиденциальность данных своей учетной записи в Telegram. Все действия, осуществленные с использованием учетной записи Пользователя, считаются осуществленными Пользователем. Пользователь самостоятельно несет ответственность перед третьими лицами за все действия, совершенные с использованием учетной записи Пользователя. Разработчик не несет ответственности за несанкционированное использование учетной записи Пользователя третьими лицами.
8.5. Пользователю запрещается:
- декомпилировать, дизассемблировать, осуществлять реверс-инжиниринг, реконструировать исходный код Приложения или пытаться получить его иными способами;
- создавать производные работы на основе Приложения;
- удалять, скрывать или изменять уведомления об интеллектуальной собственности Разработчика в Приложении.
8.6. Пользователь не должен злоупотреблять Приложением путем умышленного внедрения вирусов, троянов, червей, логических бомб или иного вредоносного или технологически опасного материала. Пользователь не должен использовать любого рода роботов, пауков (spider), скрапинг страниц или иные автоматические устройства, алгоритмы, методологии или аналогичные ручные процессы для копирования, мониторинга, получения или доступа к любой части Приложения, для попытки получения любой информации или материалов любыми средствами, которые специально не доступны через Приложение.
8.7. Пользователь не должен пытаться получить несанкционированный доступ к любой части или функции Приложения, вычислительным устройствам (серверам), на которых хранится Приложение. Пользователь не должен атаковать Приложение посредством атаки типа "отказ в обслуживании" (denial-of-service) или распределенной атаки типа "отказ в обслуживании" (distributed denial-of-service attack). Разработчик имеет право сообщить о любом таком нарушении в соответствующие правоохранительные органы и будет сотрудничать с этими органами, раскрывая им личность Пользователя. В случае такого нарушения право Пользователя на использование Приложения немедленно прекращается.
8.8. Пользователь не может использовать Приложение для любых целей, запрещенных настоящим Пользовательским соглашением, или которые являются незаконными, неприличными или оскорбительными, или для побуждения к совершению любой деятельности, нарушающей права любых третьих лиц, или любой незаконной деятельности.
8.9. Пользователь несет ответственность за настройку своих информационных технологий, компьютерных программ и платформы для доступа к Приложению.
8.10. Разработчик вправе приостановить или досрочно прекратить доступ Пользователя к Использованию Приложения, если у Разработчика есть основания полагать, что использование Приложения осуществляется или будет осуществляться Пользователем с нарушением настоящего Пользовательского соглашения, или Пользователь, по усмотрению Разработчика, совершает действия, наносящие или могущие нанести ущерб репутации Разработчика или безопасности Приложения.
8.11. Разработчик имеет право прекратить доступ к Приложению при нарушении Политики конфиденциальности или законодательства.
8.12. В случае прекращения доступа Пользователя к Приложению по основаниям, указанным в пп. 8.10 и 8.11, Разработчик вправе удержать неиспользованный остаток Telegram Stars на балансе в качестве штрафной санкции или компенсации ущерба, если нарушение Пользователя повлекло убытки для Разработчика и это предусмотрено применимым законодательством.
8.13. Разработчик не несет ответственности за контент (сообщения, файлы, данные), обрабатываемый, передаваемый или отображаемый через Приложение, а также за действия Пользователей в подключенных чатах. Ответственность за законность контента и соответствие его правилам Telegram возлагается на Пользователей.
8.14. Разработчик оставляет за собой право прекратить предоставление доступа к Приложению всем Пользователям, полностью прекратить работу Приложения или его существенных функций, уведомив об этом всех Администраторов не менее чем за 30 (Тридцать) календарных дней через Приложение, Бота и (или) по электронной почте на адрес, связанный с их Учетной записью Администратора. В этом случае Администраторам будет произведен возврат неизрасходованного остатка Telegram Stars в соответствии с п. 7.4.
## 9. Интеллектуальная собственность
9.1. При условии соблюдения Пользователем Пользовательского соглашения, Разработчик предоставляет Пользователю ограниченную, неисключительную, непередаваемую по сублицензии, отзывную, не подлежащую передаче лицензию на доступ к Приложению. Любые права, прямо не предоставленные в данном разделе, сохраняются за Разработчиком. Лицензия автоматически прекращается без уведомления при прекращении действия настоящего Пользовательского соглашения.
9.2. Все права на интеллектуальную собственность в отношении Приложения по всему миру принадлежат Разработчику, и права на Приложение лицензированы (не проданы) Пользователю. Пользователь не имеет никаких прав на интеллектуальную собственность в отношении Приложения или на них, за исключением права использовать их в соответствии с настоящим Пользовательским соглашением.
## 10. Обстоятельства непреодолимой силы (форс-мажор)
10.1. Стороны освобождаются от ответственности при наступлении обстоятельств непреодолимой силы (стихийные бедствия, войны, решения госорганов, телекоммуникационные сбои и т.п.).
10.2. Срок исполнения обязательств отодвигается на время действия форс-мажора, но не более чем на 30 (Тридцать) календарных дней.
10.3. При форс-мажоре длительностью более 30 дней Стороны проводят переговоры об альтернативных решениях или расторжении Пользовательского соглашения без возмещения убытков.
## 11. Разделимость положений
11.1. Пользователь и Разработчик соглашаются с тем, что если какая-либо часть настоящего Пользовательского соглашения или Политики конфиденциальности будет признана компетентным судом недействительной или не подлежащей защите, полностью или частично, то только такая часть настоящего Пользовательского соглашения или Политики конфиденциальности, которая объявлена недействительной или не подлежащей защите, будет считаться недействительной в данной юрисдикции, и только в той части, в которой она была признана таковой, и это не повлияет на действительность или возможность защиты в каком-либо аспекте и в любой юрисдикции других частей настоящего Пользовательского соглашения или Политики конфиденциальности, которые остаются в полной силе и действии. При этом такие недействительные положения подлежат замене положениями, максимально близкими по смыслу к исходным, которые будут признаны действительными в соответствующей юрисдикции, и подлежат применению в измененной форме (в том числе к уже установленным правоотношениям).
11.2. Признание какого-либо положения недействительным или неисполнимым не затрагивает действительность или исполнимость положений разделов 7 (Порядок и способы выплаты вознаграждения), 9 (Интеллектуальная собственность), 12 (Применимое право и разрешение споров), 15.4 (Возмещение убытков) и 15.6 (Бездействие).
## 12. Применимое право и разрешение споров
12.1. Настоящее Пользовательское соглашение регулируется и толкуется в соответствии с законодательством Российской Федерации. Вопросы, не урегулированные Пользовательским соглашением, подлежат разрешению в соответствии с законодательством Российской Федерации.
12.2. Все споры Сторон по настоящему Пользовательскому соглашению подлежат разрешению путем переписки и переговоров с использованием обязательного досудебного (претензионного) порядка. В случае невозможности достичь согласия между Сторонами путем переговоров в течение 30 (Тридцати) календарных дней с момента получения другой Стороной письменной претензии, направленной в соответствии с п. 15.2 настоящего Пользовательского соглашения, рассмотрение спора должно быть передано любой заинтересованной Стороной в суд по месту государственной регистрации Разработчика (Российская Федерация, г. Москва).
## 13. Порядок изменения Пользовательского соглашения
13.1. Настоящее Пользовательское соглашение (включая дополнения) могут быть изменены Разработчиком с уведомлением Пользователя посредством размещения новой редакции изменяемого Пользовательского соглашения на Сайте или Приложении. Внесенные Разработчиком изменения в Пользовательском соглашении, вступают в силу в день, следующий за днем опубликования таких изменений на Сайте или в Приложении (смотря что наступит раньше). Пользователь обязуется самостоятельно проверять настоящее Пользовательское соглашение на предмет внесенных изменений. Неосуществление Пользователем действий по ознакомлению не может служить основанием для неисполнения Пользователем своих обязательств и несоблюдения Пользователем ограничений, установленных настоящим Пользовательским соглашением. Разработчик рекомендует Пользователям регулярно знакомиться с актуальной редакцией Пользовательского соглашения.
13.2. Пользователь вправе отказаться от принятия изменений и дополнений в настоящее Пользовательское соглашение, что означает отказ Пользователя от использования всех предоставленных ему ранее прав.
## 14. Уступка прав (требований)
14.1. Разработчик может уступить или передать права по настоящему Пользовательскому соглашению и (или) Политике конфиденциальности полностью или частично любому физическому или юридическому лицу в любое время с согласия Пользователя или без такового. Пользователь не вправе уступать или передавать какие-либо права и обязательства, вытекающие из Пользовательского соглашения или Политики конфиденциальности, без предварительного письменного согласия Разработчика, и любая уступка или передача прав, совершенная Пользователем без такого согласия, будет недействительной.
14.2. Уступка Разработчиком прав по настоящему Соглашению третьему лицу не освобождает Разработчика от ответственности перед Пользователем за исполнение обязательств по настоящему Соглашению, возникших до момента уступки, если иное не согласовано с Пользователем или не предусмотрено законодательством.
## 15. Заключительные положения
15.1. Настоящее Пользовательское соглашение составлено на русском языке. В случае возникновения противоречий между русской версией и любыми переводами, приоритет имеет русская версия.
15.2. Все уведомления, запросы и претензии в связи с настоящим Пользовательским соглашением или использованием Приложения направляются Пользователем Разработчику по электронной почте [a-mart@ya.ru](mailto:a-mart@ya.ru) или иными способами, явно указанными Разработчиком в Приложении или на Сайте. Уведомления Разработчика Пользователю считаются направленными надлежащим образом, если они размещены в Приложении и (или) на Сайте и (или) отправлены на контактный адрес электронной почты (при наличии), связанный с учетной записью Администратора в Telegram и считаются полученными Пользователем на следующий день после их размещения и (или) отправки.
15.3. Разработчик осуществляет обработку персональных данных Пользователей исключительно в порядке и целях, определенных Политикой конфиденциальности, являющейся неотъемлемой частью настоящего Пользовательского соглашения.
15.4. Пользователь обязуется возместить Разработчику любые убытки (включая судебные издержки и разумные расходы на юридические услуги), понесенные Разработчиком в связи с нарушением Пользователем настоящего Пользовательского соглашения, законодательства или прав третьих лиц при использовании Приложения, включая убытки, возникшие в результате нарушения Пользователем прав третьих лиц (в том числе права на интеллектуальную собственность и права на конфиденциальность) при использовании Приложения.
15.5. Настоящее Пользовательское соглашение представляет собой полное соглашение между Пользователем и Разработчиком в отношении использования Приложения и заменяет собой все предыдущие устные или письменные договоренности и понимания между Сторонами по данному предмету (при их наличии).
15.6. Бездействие со стороны Разработчика в случае нарушения Пользователем положений настоящего Пользовательского соглашения не лишает Разработчика права предпринять соответствующие действия для защиты своих интересов в будущем, а также не означает отказа от своих прав в случае последующих подобных или сходных нарушений.
15.7. Настоящее Пользовательское соглашение не создает агентских, партнерских, совместных отношений или отношений франчайзинга между Пользователем и Разработчиком.
15.8. Разработчик не гарантирует совместимость Приложения со всеми устройствами, операционными системами и версиями мессенджера Telegram.
## 16. Контактная информация и реквизиты Разработчика
Индивидуальный предприниматель Мартышкин Алексей Александрович
Юридический адрес: 111394, Российская Федерация, г. Москва, ул. Перовская, д. 66, к.3, кв. 187
ОГРНИП 318774600262084
ИНН 366316608346
Телефон: +7 (926)339-04-25
Электронная почта: [a-mart@ya.ru](mailto:a-mart@ya.ru)

View File

@@ -1,63 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="32"
height="32"
viewBox="0 0 8.4666662 8.4666662"
version="1.1"
id="svg1"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1" />
<g
id="layer1">
<rect
style="fill:#000000;stroke-width:0.233149"
id="rect5"
width="6.9885192"
height="0.35581663"
x="3.114475"
y="0.86827624"
transform="matrix(0.77578367,0.63099897,-0.77578367,0.63099897,0,0)" />
<rect
style="fill:#000000;stroke-width:0.24961"
id="rect5-7"
width="7.4819207"
height="0.3809379"
x="-3.9267058"
y="5.7988153"
transform="matrix(-0.70756824,0.70664502,0.70756824,0.70664502,0,0)" />
<circle
style="fill:#000000;stroke-width:0.134869"
id="path5-8"
cx="1.5875"
cy="6.8791666"
r="1.0583333" />
<circle
style="fill:#000000;stroke-width:0.168586"
id="path5-8-5"
cx="7.1437502"
cy="7.1437502"
r="1.3229166" />
<circle
style="fill:#000000;stroke-width:0.118011"
id="path5-8-5-1"
cx="1.4552083"
cy="2.5135417"
r="0.92604166" />
<circle
style="fill:#000000;stroke-width:0.101152"
id="path5-8-5-1-7"
cx="7.1437502"
cy="1.3229166"
r="0.79374999" />
<circle
style="fill:var(--base-color);stroke-width:0.23602"
id="path5"
cx="3.96875"
cy="4.4979167"
r="1.8520833" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="32"
height="32"
viewBox="0 0 8.4666662 8.4666662"
version="1.1"
id="svg1"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<rect
style="fill:#000000;stroke-width:0.233149"
id="rect5"
width="6.9885192"
height="0.35581663"
x="3.114475"
y="0.86827624"
transform="matrix(0.77578367,0.63099897,-0.77578367,0.63099897,0,0)" />
<rect
style="fill:#000000;stroke-width:0.24961"
id="rect5-7"
width="7.4819207"
height="0.3809379"
x="-3.9267058"
y="5.7988153"
transform="matrix(-0.70756824,0.70664502,0.70756824,0.70664502,0,0)" />
<circle
style="fill:#000000;stroke-width:0.134869"
id="path5-8"
cx="1.5875"
cy="6.8791666"
r="1.0583333" />
<circle
style="fill:#000000;stroke-width:0.168586"
id="path5-8-5"
cx="7.1437502"
cy="7.1437502"
r="1.3229166" />
<circle
style="fill:#000000;stroke-width:0.118011"
id="path5-8-5-1"
cx="1.4552083"
cy="2.5135417"
r="0.92604166" />
<circle
style="fill:#000000;stroke-width:0.101152"
id="path5-8-5-1-7"
cx="7.1437502"
cy="1.3229166"
r="0.79374999" />
<circle
style="fill:var(--base-color);stroke-width:0.23602"
id="path5"
cx="3.96875"
cy="4.4979167"
r="1.8520833" />
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1,87 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="32"
height="32"
viewBox="0 0 8.4666662 8.4666662"
version="1.1"
id="svg1"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
sodipodi:docname="pN-1.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="true"
inkscape:zoom="15.78348"
inkscape:cx="8.0780662"
inkscape:cy="19.672467"
inkscape:window-width="2560"
inkscape:window-height="1001"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
<inkscape:grid
id="grid5"
units="px"
originx="0"
originy="0"
spacingx="0.26458332"
spacingy="0.26458332"
empcolor="#0099e5"
empopacity="0.30196078"
color="#0099e5"
opacity="0.14901961"
empspacing="2"
enabled="true"
visible="true" />
</sodipodi:namedview>
<defs
id="defs1" />
<g
inkscape:label="Слой 1"
inkscape:groupmode="layer"
id="layer1">
<path
id="rect5"
style="fill:#00d400;stroke-width:0.233149"
d="M 5.4832926 -3.3867493 L 5.7392718 -0.88528268 A 2.075472 1.6881261 45 0 0 4.6544407 -0.46135405 A 2.075472 1.6881261 45 0 0 4.2505334 0.86798056 L 3.1143835 0.86822985 L 3.114654 1.2242079 L 4.3268544 1.2240716 A 2.075472 1.6881261 45 0 0 4.9283355 2.1999117 A 2.075472 1.6881261 45 0 0 6.1216465 2.8549985 L 6.2608319 4.214514 L 6.6480286 4.2539966 L 6.5088433 2.894481 A 2.075472 1.6881261 45 0 0 7.5896013 2.4738066 A 2.075472 1.6881261 45 0 0 8.0016857 1.2239238 L 10.102884 1.2241825 L 10.103023 0.86861392 L 7.9375784 0.86872246 A 2.075472 1.6881261 45 0 0 7.3157064 -0.18745917 A 2.075472 1.6881261 45 0 0 6.1262119 -0.8447245 L 5.8704894 -3.3472668 L 5.4832926 -3.3867493 z "
transform="matrix(0.77578367,0.63099897,-0.77578367,0.63099897,0,0)" />
<circle
style="fill:#ff0000;stroke-width:0.134869"
id="path5-8"
cx="1.5875"
cy="6.8791666"
r="1.0583333" />
<circle
style="fill:#ff0000;stroke-width:0.168586"
id="path5-8-5"
cx="7.1437502"
cy="7.1437502"
r="1.3229166" />
<circle
style="fill:#ff0000;stroke-width:0.118011"
id="path5-8-5-1"
cx="1.4552083"
cy="2.5135417"
r="0.92604166" />
<circle
style="fill:#ff0000;stroke-width:0.101152"
id="path5-8-5-1-7"
cx="7.1437502"
cy="1.3229166"
r="0.79374999" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -13,6 +13,7 @@ export default defineBoot(({ app }) => {
if (window.Telegram?.WebApp) { if (window.Telegram?.WebApp) {
const webApp = window.Telegram.WebApp const webApp = window.Telegram.WebApp
webApp.ready() webApp.ready()
webApp.SettingsButton.isVisible = true
app.config.globalProperties.$tg = webApp app.config.globalProperties.$tg = webApp
app.provide('tg', webApp) app.provide('tg', webApp)
} }

View File

@@ -0,0 +1,47 @@
<template>
<q-markdown
:src="markdownContent"
no-heading-anchor-links
/>
</template>
<script setup lang="ts">
import { computed } from 'vue'
const props = defineProps({
locale: {
type: String,
required: true
},
documentName: {
type: String,
required: true
}
})
// Импорт всех Markdown-файлов как raw-строк
const mdFiles = import.meta.glob('assets/docs/*.md', {
query: '?raw',
import: 'default',
eager: true
})
const markdownContent = computed(() => {
const baseLang = props.locale.split('-')[0]?.toLowerCase()
// Формируем имена файлов
const localizedFileName = `${props.documentName}_${baseLang}.md`
const fallbackFileName = `${props.documentName}_en.md`
// Находим пути к файлам
const filePaths = Object.keys(mdFiles)
const localizedPath = filePaths.find(path => path.endsWith(localizedFileName))
const fallbackPath = filePaths.find(path => path.endsWith(fallbackFileName))
// Возвращаем контент в порядке приоритета
if (localizedPath) return mdFiles[localizedPath]
if (fallbackPath) return mdFiles[fallbackPath]
return `# Document load error\n> Missing files for ${props.documentName}`
})
</script>

View File

@@ -10,7 +10,7 @@
<q-step <q-step
:name="1" :name="1"
:title="$t('account_helper__enter_email')" :title="$t('account_helper__enter_email')"
:done="step > 1" :done="step>1"
> >
<q-input <q-input
v-model="login" v-model="login"
@@ -23,7 +23,7 @@
no-error-icon no-error-icon
@focus="($refs.emailInput as typeof QInput)?.resetValidation()" @focus="($refs.emailInput as typeof QInput)?.resetValidation()"
ref="emailInput" ref="emailInput"
:disable="type === 'changePwd'" :disable="type==='changePwd'"
/> />
<q-stepper-navigation> <q-stepper-navigation>
<q-btn <q-btn
@@ -31,6 +31,8 @@
color="primary" color="primary"
:label="$t('continue')" :label="$t('continue')"
:disabled="!isEmailValid" :disabled="!isEmailValid"
:unelevated="!isEmailValid"
class="fix-disabled-btn"
/> />
</q-stepper-navigation> </q-stepper-navigation>
</q-step> </q-step>
@@ -38,7 +40,7 @@
<q-step <q-step
:name="2" :name="2"
:title="$t('account_helper__confirm_email')" :title="$t('account_helper__confirm_email')"
:done="step > 2" :done="step>2"
> >
<div class="q-pb-md">{{$t('account_helper__confirm_email_message')}}</div> <div class="q-pb-md">{{$t('account_helper__confirm_email_message')}}</div>
<q-input <q-input
@@ -55,11 +57,13 @@
@click="handleSubmit" @click="handleSubmit"
color="primary" color="primary"
:label="$t('continue')" :label="$t('continue')"
:disable="code.length === 0" :disable="code.length===0"
:unelevated="code.length===0"
class="fix-disabled-btn"
/> />
<q-btn <q-btn
flat flat
@click="step = 1" @click="step=1"
color="primary" color="primary"
:label="$t('back')" :label="$t('back')"
class="q-ml-sm" class="q-ml-sm"
@@ -76,7 +80,7 @@
dense dense
filled filled
autofocus autofocus
:label = "$t('account_helper__password')" :label="$t('account_helper__password')"
:type="isPwd ? 'password' : 'text'" :type="isPwd ? 'password' : 'text'"
hide-hint hide-hint
:hint="passwordHint" :hint="passwordHint"
@@ -91,7 +95,7 @@
color="grey-5" color="grey-5"
:name="isPwd ? 'mdi-eye-off-outline' : 'mdi-eye-outline'" :name="isPwd ? 'mdi-eye-off-outline' : 'mdi-eye-outline'"
class="cursor-pointer" class="cursor-pointer"
@click="isPwd = !isPwd" @click="isPwd=!isPwd"
/> />
</template> </template>
</q-input> </q-input>
@@ -101,11 +105,13 @@
@click="handleSubmit" @click="handleSubmit"
color="primary" color="primary"
:label="$t('account_helper__finish')" :label="$t('account_helper__finish')"
:disabled = "!isPasswordValid" :disabled="!isPasswordValid"
:unelevated="!isPasswordValid"
class="fix-disabled-btn"
/> />
<q-btn <q-btn
flat flat
@click="step = 2" @click="step=2"
color="primary" color="primary"
:label="$t('back')" :label="$t('back')"
class="q-ml-sm" class="q-ml-sm"

View File

@@ -4,79 +4,40 @@
{{ $t(type + '__title') }} {{ $t(type + '__title') }}
</template> </template>
<pn-scroll-list> <pn-scroll-list>
<div class="q-px-md"> <markdown-viewver
<div class="q-pa-md"
v-if="fileText" :locale
style="white-space: pre-wrap;" :documentName = "getDocumentName()"
> />
{{ fileText }}
</div>
<div
v-else
align="center"
class="text-negative"
>
{{ $t(type + '__not_ready') }}
</div>
</div>
</pn-scroll-list> </pn-scroll-list>
<div
class="flex column justify-center items-center w100"
style="position: absolute; bottom: 0;"
v-if="isLoading"
>
<q-linear-progress indeterminate />
</div>
</pn-page-card> </pn-page-card>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import { useSettingsStore } from 'stores/settings' import { useSettingsStore } from 'stores/settings'
import MarkdownViewver from 'components/MarkdownViewver.vue'
const props = defineProps<{ const props = defineProps<{
type: 'terms_of_use' | 'privacy' type: 'terms_of_use' | 'privacy' | 'consent'
}>() }>()
const settingsStore = useSettingsStore() const settingsStore = useSettingsStore()
const fileText = ref<string | null>('') const DEFAULT_LOCALE = 'ru'
const isLoading = ref(true) const locale = ref('ru')
const DEFAULT_LANG = 'ru'
const baseDocName = props.type === 'terms_of_use' const getDocumentName = () =>{
? 'Terms_of_use' switch(props.type) {
: 'Privacy' case 'terms_of_use': return 'Terms_of_use'
case 'privacy': return 'Privacy-Policy'
const parseLocale = (locale: string) => locale.split(/[-_]/)[0] || DEFAULT_LANG case 'consent': return 'Consent_to_Personal_Data_Processing'
const fetchDocument = async (language: string) => {
try {
const response = await fetch(`/admin/doc/${baseDocName}_${language}.txt`)
if (!response.ok) throw new Error(`HTTP ${response.status}`)
return await response.text()
} catch (error) {
console.error(`Failed to load ${language} version:`, error)
return null
} }
} }
onMounted(async () => { const parseLocale = (locale: string) => locale.split(/[-_]/)[0] || DEFAULT_LOCALE
try {
const lang = parseLocale(settingsStore.settings.locale)
fileText.value = await fetchDocument(lang) onMounted(() => {
locale.value = parseLocale(settingsStore.settings.locale)
if (!fileText.value && lang !== DEFAULT_LANG) {
fileText.value = await fetchDocument(DEFAULT_LANG)
}
if (!fileText.value) throw new Error('All loading attempts failed')
} catch (error) {
console.error('Document loading failed:', error)
} finally {
isLoading.value = false
}
}) })
</script> </script>

View File

@@ -6,7 +6,7 @@
<slot name="title"/> <slot name="title"/>
</div> </div>
<slot/> <slot/>
<div class="bg-white w100 q-ma-none q-px-md"> <div class="bg-white w100 q-ma-none q-px-md flex items-center">
<slot name="footer"/> <slot name="footer"/>
</div> </div>
</template> </template>

View File

@@ -19,10 +19,10 @@ export function useUserSection() {
const section3 = ( const section3 = (
user.company_id && companiesStore.companyById(user.company_id) user.company_id && companiesStore.companyById(user.company_id)
? companiesStore.companyById(user.company_id)?.name + ((user.role || user.department) ? ' / ' : '') ? companiesStore.companyById(user.company_id)?.name + ((user.role || user.department) ? ' - ' : '')
: '' : ''
) + ) +
(user.department ? user.department + (user.role ? ' / ' : '') : '') + (user.department ? user.department + (user.role ? ' - ' : '') : '') +
(user.role ?? '') (user.role ?? '')
return { return {

View File

@@ -1,4 +1,4 @@
$primary : #27A7E7; $primary : #3390ec;
$secondary : #26A69A; $secondary : #26A69A;
$accent : #9C27B0; $accent : #9C27B0;
@@ -12,7 +12,7 @@ $warning : #F2C037;
$lightgrey : #DCDCDC; $lightgrey : #DCDCDC;
$brand: #27A7E7; $brand: #3390ec;
$brand2: #F36D3A; $brand2: #F36D3A;
$body-font-size: var(--dynamic-font-size); $body-font-size: var(--dynamic-font-size);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -40,12 +40,26 @@
</q-list> </q-list>
</pn-scroll-list> </pn-scroll-list>
</pn-page-card> </pn-page-card>
<pn-small-dialog
v-model="showStopUsingDialog"
icon="mdi-close-box-outline"
color="negative"
title="account__stop_using_dialog_title"
message1="account__stop_using_dialog_message1"
message2="account__stop_using_dialog_message2"
mainBtnLabel="account__stop_using_dialog_btn_ok"
@clickMainBtn="onConfirmStopUsing"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { computed } from 'vue' import { computed, ref, inject } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { useAuthStore } from 'stores/auth' import { useAuthStore } from 'stores/auth'
import type { WebApp } from '@twa-dev/types'
const tg = inject('tg') as WebApp
const router = useRouter() const router = useRouter()
const authStore = useAuthStore() const authStore = useAuthStore()
@@ -68,16 +82,22 @@
{ id: 5, name: 'account__company_data', icon: 'mdi-account-group-outline', description: 'account__company_data_description', pathName: 'your_company' }, { id: 5, name: 'account__company_data', icon: 'mdi-account-group-outline', description: 'account__company_data_description', pathName: 'your_company' },
{ id: 6, name: 'account__settings', icon: 'mdi-cog-outline', description: 'account__settings_description', iconColor: 'info', pathName: 'settings' }, { id: 6, name: 'account__settings', icon: 'mdi-cog-outline', description: 'account__settings_description', iconColor: 'info', pathName: 'settings' },
{ id: 7, name: 'account__support', icon: 'mdi-lifebuoy', description: 'account__support_description', iconColor: 'info', pathName: 'support' }, { id: 7, name: 'account__support', icon: 'mdi-lifebuoy', description: 'account__support_description', iconColor: 'info', pathName: 'support' },
{ id: 9, name: 'account__terms_of_use', icon: 'mdi-book-open-variant-outline', description: '', iconColor: 'grey', pathName: 'terms' }, { id: 8, name: 'account__terms_of_use', icon: 'mdi-book-open-variant-outline', description: '', iconColor: 'grey', pathName: 'terms' },
{ id: 10, name: 'account__privacy', icon: 'mdi-lock-outline', description: '', iconColor: 'grey', pathName: 'privacy' } { id: 9, name: 'account__privacy', icon: 'mdi-lock-outline', description: '', iconColor: 'grey', pathName: 'privacy' },
{ id: 10, name: 'account__stop_using', icon: 'mdi-close-box-outline', description: 'account__stop_using_description', iconColor: 'negative', pathName: 'stop_using' }
])) ]))
const displayItems = computed(() => ( const displayItems = computed(() => (
items.value.filter((item: ItemList) => !('display' in item) || item.display === true) items.value.filter((item: ItemList) => !('display' in item) || item.display === true)
)) ))
const showStopUsingDialog = ref(false)
async function goTo (path: string) { async function goTo (path: string) {
await router.push({ name: path }) if (path !== 'stop_using') {
await router.push({ name: path })
} else {
showStopUsingDialog.value = true
}
} }
async function logout () { async function logout () {
@@ -85,6 +105,10 @@
await router.push({ name: 'login' }) await router.push({ name: 'login' })
} }
function onConfirmStopUsing () {
tg.close()
}
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@@ -17,7 +17,7 @@
<pn-scroll-list> <pn-scroll-list>
<div <div
v-if="chat" v-if="chat"
class="flex column items-center q-pa-md q-pb-lg" class="flex column items-center q-pa-md"
> >
<pn-auto-avatar <pn-auto-avatar
:img="chat.logo" :img="chat.logo"
@@ -25,17 +25,23 @@
size="100px" size="100px"
rounded rounded
/> />
<div
class="flex row items-start justify-center q-pt-md text-bold"
align="center"
>
{{ chat.name }}
</div>
<div <div
v-if="chat.description" v-if="chat.description"
class="flex row items-start justify-center q-pt-md" class="flex row items-start justify-center text-caption"
align="center"
> >
{{ chat.description }} {{ chat.description }}
</div> </div>
</div> </div>
<q-list separator v-if="chatUsers.length!==0"> <q-list separator v-if="chatUsers.length!==0">
<q-item-label header> <q-item-label class="text-caption text-bold q-py-none" header>
{{ $t('chat_page__members') + ' (' + chatUsers.length +')' }} {{ $t('chat_card__members') + ' (' + chatUsers.length +')' }}
</q-item-label> </q-item-label>
<q-item <q-item
v-for="item in chatUsers" v-for="item in chatUsers"
@@ -61,7 +67,7 @@
</q-badge> </q-badge>
{{item.section1}} {{item.section1}}
</q-item-label> </q-item-label>
<q-item-label lines="1" caption v-if="item.section3"> <q-item-label lines="2" caption v-if="item.section3">
{{item.section3}} {{item.section3}}
</q-item-label> </q-item-label>
<q-item-label caption lines="2"> <q-item-label caption lines="2">
@@ -113,9 +119,9 @@
watch(() => chatsStore.isInit, initChat) watch(() => chatsStore.isInit, initChat)
function onSubmit () { async function onSubmit () {
if (chat.value && chat.value.invite_link) tg.openTelegramLink(chat.value.invite_link) if (chat.value && chat.value.invite_link) tg.openTelegramLink(chat.value.invite_link)
if (chat && chat.value) chatsStore.getChatUsers(chat.value.id) if (chat.value) await chatsStore.getChatUsers(chat.value.id)
} }
const users = usersStore.getUsers const users = usersStore.getUsers
@@ -123,8 +129,8 @@
const { userSection } = useUserSection() const { userSection } = useUserSection()
const chatUsers = computed(() => { const chatUsers = computed(() => {
if (!chat || !chat.value) return [] if (!chat.value) return []
const idSet = new Set(chat.value.chat_users) const idSet = new Set(chat.value.users)
const arr = users.filter(el => idSet.has(el.id)) const arr = users.filter(el => idSet.has(el.id))
return arr.map(el => ({ return arr.map(el => ({
...el, ...el,

View File

@@ -5,18 +5,23 @@
title="company_edit__title_card" title="company_edit__title_card"
btnText="company_edit__btn" btnText="company_edit__btn"
@update="updateCompany" @update="updateCompany"
> >
<template #myCompany v-if="company.is_own"> <template #myCompany v-if="company.is_own">
<div class="q-mb-md flex w100 justify-center"> <div class="q-mb-md flex w100 justify-center">
<div class="flex items-center text-amber-10"> <div class="flex items-center text-amber-10">
<q-icon name="star" class="q-pr-xs"/> <q-icon name="star" class="q-pr-xs"/>
{{ $t('company_edit__my_company') }} {{ $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') }}
</div>
<div class="text-caption text-primary cursor-pointer" align="center" @click="goMyCompany">
{{ $t('company_edit__my_company_href') }}
</div>
</div>
</div> </div>
<div class="text-caption" align="center" style="white-space: pre-wrap;"> </template>
{{ $t('company_edit__my_company_hint') }}
</div>
</div>
</template>
</company-block> </company-block>
</template> </template>
@@ -50,6 +55,10 @@
if (isInit) initCompany() if (isInit) initCompany()
}) })
async function goMyCompany () {
await router.push({ name: 'your_company' })
}
async function updateCompany(companyData: CompanyParams) { async function updateCompany(companyData: CompanyParams) {
if (companyId.value) { if (companyId.value) {
await companiesStore.update(companyId.value, companyData) await companiesStore.update(companyId.value, companyData)

View File

@@ -1,17 +1,27 @@
<template> <template>
<pn-page-card> <pn-page-card>
<template #title> <template #title>
{{$t('company__mask')}} {{$t('mask__title')}}
<q-btn
v-if="!checkIsDirty(mask, originalMask)"
@click = "updateCompanies()"
flat round
icon="mdi-check"
/>
</template> </template>
<template #footer>
<q-btn
rounded color="primary"
class="w100 q-mt-md q-mb-xs fix-disabled-btn"
@click="updateCompanies()"
>
{{ $t('mask__btn_ok') }}
</q-btn>
</template>
<pn-scroll-list> <pn-scroll-list>
<template #card-body-header> <template #card-body-header>
<div style="min-height: var(--top-raduis);"/> <div class="q-ma-sm q-pa-sm bg-grey-11 flex no-wrap items-center" style="border-radius: var(--top-raduis);">
<q-icon name="mdi-information q-pr-xs" size="sm" color="primary"/>
<span class="text-caption">
{{ $t('mask__info_block')}}
</span>
</div>
</template> </template>
<q-table <q-table
flat flat
@@ -49,7 +59,6 @@
</q-tr> </q-tr>
</template> </template>
<template #body="props"> <template #body="props">
<q-tr :props="props"> <q-tr :props="props">
<q-td key="checkbox" :props="props"> <q-td key="checkbox" :props="props">
@@ -144,7 +153,6 @@
<q-card-section class="q-pt-sm"> <q-card-section class="q-pt-sm">
<p>{{ $t('mask__help_message1')}}</p> <p>{{ $t('mask__help_message1')}}</p>
<p>{{ $t('mask__help_message2')}}</p> <p>{{ $t('mask__help_message2')}}</p>
<p>{{ $t('mask__help_message3')}}</p>
</q-card-section> </q-card-section>
</q-card> </q-card>
</q-dialog> </q-dialog>
@@ -152,9 +160,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed, onMounted } from 'vue' import { ref, computed, watch } from 'vue'
import { useCompaniesStore } from 'stores/companies' import { useCompaniesStore } from 'stores/companies'
import type { CompanyMask } from 'types/Company'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
const showDialogHelp = ref<boolean>(false) const showDialogHelp = ref<boolean>(false)
@@ -164,6 +171,12 @@
const companies = computed(() => companiesStore.companies) const companies = computed(() => companiesStore.companies)
const companiesMask = computed(() => companiesStore.companiesMask) const companiesMask = computed(() => companiesStore.companiesMask)
const tableColumns = [
{ name: 'checkbox', field: 'checkbox', label: 'checkbox', sortable: false, style: "width: 10%" },
{ name: 'name', field: 'name', align: 'left' as const, label: 'name', sortable: false, style: "width: 45% !important; text-wrap: auto" },
{ name: 'visible', field: 'visible', align: 'center' as const, label: 'visible', sortable: false, style: "width: 45% !important" }
]
interface DisplayCompany { interface DisplayCompany {
id: number id: number
name: string name: string
@@ -174,15 +187,36 @@
hasFocus: boolean hasFocus: boolean
} }
//
const displayCompanies = ref<DisplayCompany[]>([]) const displayCompanies = ref<DisplayCompany[]>([])
const originalMask = ref<CompanyMask[]>([])
const tableColumns = [ watch(
{ name: 'checkbox', field: 'checkbox', label: 'checkbox', sortable: false, style: "width: 10%" }, () => [companies.value, companiesMask.value],
{ name: 'name', field: 'name', align: 'left' as const, label: 'name', sortable: false, style: "width: 45% !important; text-wrap: auto" }, () => {
{ name: 'visible', field: 'visible', align: 'center' as const, label: 'visible', sortable: false, style: "width: 45% !important" } updateDisplayCompanies()
] },
{ immediate: true, deep: true }
)
function updateDisplayCompanies() {
if (companies.value.length === 0 || companiesMask.value.length === 0) return
displayCompanies.value = companies.value
.filter(el => !el.is_own)
.map(el => ({
id: el.id,
name: el.name,
logo: el.logo ?? '',
masked: companiesStore.checkCompanyMasked(el.id),
company_list: getList(el.id),
isMenuOpen: false,
hasFocus: false
}))
}
function getList (companyId: number) {
const company = companiesMask.value.find(el => Number(el.company_id) === companyId)
return company?.company_list ?? []
}
const mask = computed(() => displayCompanies.value const mask = computed(() => displayCompanies.value
.filter(el => el.masked) .filter(el => el.masked)
@@ -193,8 +227,8 @@
.sort((a, b) => compareNumbers(a.company_id, b.company_id)) .sort((a, b) => compareNumbers(a.company_id, b.company_id))
) )
function getCompanyById(id: number) { function getCompanyById (id: number) {
return companies.value.find(c => c.id === id); return companies.value.find(c => c.id === id)
} }
function companiesSelect (id :number) { function companiesSelect (id :number) {
@@ -220,61 +254,6 @@
return a < b ? -1 : 1 return a < b ? -1 : 1
} }
function checkIsDirty (arr1: CompanyMask[], arr2: CompanyMask[]): boolean {
// Проверка длины массивов
if (arr1.length !== arr2.length) return false
// Функция для нормализации объекта в строковый ключ
const getKey = (obj: { company_id: number; company_list: number[] }): string => {
const sortedList = [...obj.company_list].sort(compareNumbers)
return `${obj.company_id}|${sortedList.join(',')}`
}
// Создаем Map для подсчета объектов в первом массиве
const countMap = new Map<string, number>()
for (const item of arr1) {
const key = getKey(item)
countMap.set(key, (countMap.get(key) || 0) + 1)
}
// Проверяем объекты второго массива
for (const item of arr2) {
const key = getKey(item)
const count = countMap.get(key) || 0
if (count === 0) return false
countMap.set(key, count - 1)
}
return true
}
onMounted(() => {
function getList (companyId: number) {
const company = companiesMask.value.find(el => el.company_id === companyId)
return company?.company_list ?? []
}
displayCompanies.value = companies.value
.filter(el => !el.is_own)
.map(el => ({
id: el.id,
name: el.name,
logo: el?.logo ?? '',
masked: companiesStore.checkCompanyMasked(el.id),
company_list: getList(el.id),
isMenuOpen: false,
hasFocus: false
}))
console.log(companies.value)
console.log(displayCompanies.value)
originalMask.value = [ ...(companiesMask.value.sort((a, b) => compareNumbers(a.company_id, b.company_id))) ]
})
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@@ -306,4 +285,3 @@
color: 'brand'; color: 'brand';
} }
</style> </style>

View File

@@ -74,8 +74,9 @@
<q-btn <q-btn
@click="sendAuth()" @click="sendAuth()"
color="primary" color="primary"
class="w100 q-my-md" class="w100 q-my-md fix-disabled-btn"
:disabled="!isEmailValid || !isPasswordValid" :disabled="!isEmailValid || !isPasswordValid"
:unelevated="!isEmailValid || !isPasswordValid"
> >
{{$t('login__sign_in')}} {{$t('login__sign_in')}}
</q-btn> </q-btn>

View File

@@ -69,17 +69,29 @@
{{item.description}} {{item.description}}
</q-item-label> </q-item-label>
</q-item-section> </q-item-section>
<q-item-section side class="text-caption "> <q-item-section side top>
<div class="flex items-center column"> <q-item-label lines="1" class="text-caption">
<div class="flex items-center"> <div class="flex items-center">
<q-icon name="mdi-chat-outline"/> <div class="flex items-center">
<span>{{ item.chat_count }} </span> <q-icon name="mdi-chat-outline"/>
<span>{{ item.chat_count }} </span>
</div>
<div class="flex items-center q-ml-xs">
<q-icon name="mdi-account-outline"/>
<span>{{ item.user_count }}</span>
</div>
</div> </div>
<div class="flex items-center"> </q-item-label>
<q-icon name="mdi-account-outline"/> <q-item-label>
<span>{{ item.user_count }}</span> <q-btn
</div> color="grey"
</div> size="sm"
dense flat round
icon="mdi-pencil"
class="q-ml-sm"
@click.stop="editProject(item.id)"
/>
</q-item-label>
</q-item-section> </q-item-section>
</q-item> </q-item>
</q-slide-item> </q-slide-item>
@@ -225,6 +237,10 @@
await router.push({ name: 'chats', params: { id }}) await router.push({ name: 'chats', params: { id }})
} }
async function editProject (id: number) {
await router.push({ name: 'project_info', params: { id }})
}
async function goAccount () { async function goAccount () {
await router.push({ name: 'account' }) await router.push({ name: 'account' })
} }

View File

@@ -0,0 +1,104 @@
<template>
<pn-page-card>
<template #title>
{{$t('agreements__title')}}
</template>
<pn-scroll-list>
<div class="flex column w100 q-pa-md q-gutter-y-md">
<div>
{{ $t('agreements__description') }}
</div>
<div class="flex items-center no-wrap">
<q-checkbox v-model="agreement" val="1" class="q-pr-sm"/>
<span>
{{ $t('agreements__checkbox_agreement_terms') + ' ' }}
<span
@click="router.push({ name: 'terms' })"
class="cursor-pointer"
style="text-decoration: underline;"
>
{{ $t('agreements__checkbox_agreement_terms_doc') }}
</span>
</span>
</div>
<div class="flex items-center no-wrap">
<q-checkbox v-model="agreement" val="2" class="q-pr-sm"/>
<span>
{{ $t('agreements__checkbox_agreement_consent') + ' ' }}
<span
@click="router.push({ name: 'consent' })"
class="cursor-pointer"
style="text-decoration: underline;"
>
{{ $t('agreements__checkbox_agreement_consent_doc') }}
</span>
{{ ' ' + $t('agreements__checkbox_agreement_privacy') + ' ' }}
<span
@click="router.push({ name: 'consent' })"
class="cursor-pointer"
style="text-decoration: underline;"
>
{{ $t('agreements__checkbox_agreement_privacy_doc') }}
</span>
</span>
</div>
</div>
</pn-scroll-list>
<template #footer>
<div class="flex no-wrap justify-center w100 q-gutter-x-md q-pb-md">
<q-btn
flat
color="negative"
no-caps
style="opacity: 0.6"
@click="onDecline"
class="col"
>
<div class="flex column items-center">
{{ $t('agreements__btn_decline') }}
<span class="text-caption">
{{ $t('agreements__btn_decline_description') }}
</span>
</div>
</q-btn>
<q-btn
color="primary"
no-caps
:disable="agreement.length !== 2"
@click="onSubmit"
class="fix-disabled-btn col"
>
{{$t('agreements__btn_agree')}}
</q-btn>
</div>
</template>
</pn-page-card>
</template>
<script setup lang="ts">
import { ref, inject } from 'vue'
import { useRouter } from 'vue-router'
import { useAuthStore } from 'stores/auth'
import type { WebApp } from '@twa-dev/types'
const tg = inject('tg') as WebApp
function onDecline () {
tg.close()
}
const authStore = useAuthStore()
const router = useRouter()
async function onSubmit () {
await authStore.termsAccepted()
await router.push({ name: 'projects' })
}
const agreement = ref([])
</script>
<style>
</style>

View File

@@ -0,0 +1,10 @@
<template>
<doc-block type="consent"/>
</template>
<script setup lang="ts">
import docBlock from 'components/docBlock.vue'
</script>
<style>
</style>

View File

@@ -52,12 +52,17 @@
</div> </div>
<q-btn <q-btn
@click="editProject" @click="toProjects"
flat round flat
color="white" no-caps
icon="edit" dense
size="md" class="q-ml-xl"
/> >
<span class="flex items-center no-wrap text-caption">
{{ $t('header__to_projects') }}
<q-icon name="mdi-chevron-right"/>
</span>
</q-btn>
</div> </div>
</template> </template>
@@ -93,9 +98,8 @@
expandProjectInfo.value = !expandProjectInfo.value expandProjectInfo.value = !expandProjectInfo.value
} }
async function editProject () { async function toProjects () {
if (currentProjectId.value) await router.push({ name: 'projects' })
await router.push({ name: 'project_info', params: { id: currentProjectId.value } })
} }
interface sizeParams { interface sizeParams {

View File

@@ -45,7 +45,7 @@
<q-item-label lines="1" class="text-bold" v-if="item.section1"> <q-item-label lines="1" class="text-bold" v-if="item.section1">
{{item.section1}} {{item.section1}}
</q-item-label> </q-item-label>
<q-item-label lines="1" caption v-if="item.section3"> <q-item-label lines="2" caption v-if="item.section3">
{{item.section3}} {{item.section3}}
</q-item-label> </q-item-label>
<q-item-label caption lines="2"> <q-item-label caption lines="2">
@@ -172,7 +172,7 @@
<q-item-label lines="1" class="text-bold" v-if="item.section1"> <q-item-label lines="1" class="text-bold" v-if="item.section1">
{{item.section1}} {{item.section1}}
</q-item-label> </q-item-label>
<q-item-label lines="1" caption v-if="item.section3"> <q-item-label lines="2" caption v-if="item.section3">
{{item.section3}} {{item.section3}}
</q-item-label> </q-item-label>
<q-item-label caption lines="2"> <q-item-label caption lines="2">

View File

@@ -37,6 +37,14 @@ export default defineRouter(function (/* { store, ssrContext } */) {
const authStore = useAuthStore() const authStore = useAuthStore()
const projectsStore = useProjectsStore() const projectsStore = useProjectsStore()
if (to.name === '404' || to.name === 'terms' || to.name === 'privacy' || to.name === 'consent') return true
if (to.name === 'login') return true
if (to.name === 'agreements' && authStore.isAuth) return true
// if (!authStore.isTermsAccepted && authStore.isAuth) return { name: 'agreements' }
if (to.meta.guestOnly && authStore.isAuth) { if (to.meta.guestOnly && authStore.isAuth) {
return { name: 'projects' } return { name: 'projects' }
} }

View File

@@ -135,6 +135,11 @@ const routes: RouteRecordRaw[] = [
component: () => import('pages/account/SubscribePage.vue'), component: () => import('pages/account/SubscribePage.vue'),
meta: { requiresAuth: true } meta: { requiresAuth: true }
}, },
{
name: 'agreements',
path: '/agreements',
component: () => import('pages/account/AgreementsPage.vue')
},
{ {
name: 'terms', name: 'terms',
path: '/terms-of-use', path: '/terms-of-use',
@@ -143,12 +148,17 @@ const routes: RouteRecordRaw[] = [
{ {
name: 'privacy', name: 'privacy',
path: '/privacy', path: '/privacy',
component: () => import('pages/account/PrivacyPage.vue'), component: () => import('pages/account/PrivacyPage.vue')
},
{
name: 'consent',
path: '/consent-pd',
component: () => import('pages/account/ConsentPage.vue')
}, },
{ {
name: 'support', name: 'support',
path: '/support', path: '/support',
component: () => import('src/pages/account/SupportPage.vue'), component: () => import('src/pages/account/SupportPage.vue')
}, },
{ {
name: 'your_company', name: 'your_company',

View File

@@ -33,6 +33,7 @@ export type AuthFlowType = keyof typeof ENDPOINT_MAP
export const useAuthStore = defineStore('auth', () => { export const useAuthStore = defineStore('auth', () => {
const customer = ref<Customer | null>(null) const customer = ref<Customer | null>(null)
const isTermsAccepted = ref(false)
const wsEvent = ref<WSMessage | null>(null) const wsEvent = ref<WSMessage | null>(null)
const projectsStore = useProjectsStore() const projectsStore = useProjectsStore()
@@ -126,8 +127,20 @@ export const useAuthStore = defineStore('auth', () => {
if (response.status === 200 && customer.value) customer.value.company = companyData if (response.status === 200 && customer.value) customer.value.company = companyData
} }
// agreement
async function termsAccepted () {
const { data } = await api.post('/terms/accept')
if (data.success) isTermsAccepted.value = true
}
async function termsRevoked () {
const { data } = await api.post('/terms/revoke')
if (data.success) isTermsAccepted.value = false
}
return { return {
customer, customer,
isTermsAccepted,
isAuth, isAuth,
wsEvent, wsEvent,
initialize, initialize,
@@ -142,6 +155,8 @@ export const useAuthStore = defineStore('auth', () => {
confirmCurrentEmailCode, confirmCurrentEmailCode,
getCodeNewEmail, getCodeNewEmail,
confirmNewEmailCode, confirmNewEmailCode,
setNewEmailPassword setNewEmailPassword,
termsAccepted,
termsRevoked
} }
}) })

View File

@@ -18,12 +18,7 @@ export const useCompaniesStore = defineStore('companies', () => {
const { data }= await api.get('/project/' + currentProjectId.value + '/company') const { data }= await api.get('/project/' + currentProjectId.value + '/company')
const companiesAPI = data.data const companiesAPI = data.data
companies.value.push(...(companiesAPI.sort((a: Company, b: Company) => (a.id - b.id)))) companies.value.push(...(companiesAPI.sort((a: Company, b: Company) => (a.id - b.id))))
companiesMask.value = [ await getCompanyMasked()
{ "company_id": 11, "company_list": [ 9, 12 ] },
{ "company_id": 9, "company_list": [ 11, 12 ] },
{ "company_id": 12, "company_list": [ 9, 10, 13 ] }
]
// await getCompanyMasked()
isInit.value = true isInit.value = true
} }
@@ -61,16 +56,17 @@ export const useCompaniesStore = defineStore('companies', () => {
async function getCompanyMasked () { async function getCompanyMasked () {
const { data } = await api.get('/project/' + currentProjectId.value + '/company/mapping') const { data } = await api.get('/project/' + currentProjectId.value + '/company/mapping')
const companiesMaskAPI = data.data const companiesMaskAPI = data.data // arr [company_id, company_list[]]
companiesMask.value = companiesMaskAPI companiesMask.value = companiesMaskAPI
console.log(11, companiesMaskAPI)
} }
function checkCompanyMasked (id: number) { function checkCompanyMasked (id: number) {
return companiesMask.value.some(el => el.company_id === id) return companiesMask.value.some(el => Number(el.company_id) === id)
} }
async function updateMask (mask: CompanyMask[]) { async function updateMask (mask: CompanyMask[]) {
const { data } = await api.post('/project/' + currentProjectId.value + '/company/mapping', mask) const { data } = await api.put('/project/' + currentProjectId.value + '/company/mapping', mask)
const maskAPI = data.data const maskAPI = data.data
companiesMask.value = maskAPI companiesMask.value = maskAPI
} }

View File

@@ -11,7 +11,7 @@ interface Chat {
logo: string | null logo: string | null
owner_id?: number owner_id?: number
invite_link: string invite_link: string
chat_users: number [] users: number []
[key: string]: number | string | boolean | null | number[] [key: string]: number | string | boolean | null | number[]
} }

View File

@@ -1,7 +1,7 @@
{ {
"extends": "./.quasar/tsconfig.json", "extends": "./.quasar/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"types": ["@twa-dev/types", "node"] "types": ["@twa-dev/types", "node", "vite/client"]
}, },
"include": ["src/**/*", "types/**/*"] "include": ["src/**/*", "types/**/*"]
} }