Compare commits
2 Commits
629d03cdef
...
cf634f766f
| Author | SHA1 | Date | |
|---|---|---|---|
| cf634f766f | |||
| f97f4b5d96 |
355
dist/3rdpartylicenses.txt
vendored
355
dist/3rdpartylicenses.txt
vendored
@@ -1,355 +0,0 @@
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Package: @angular/forms
|
||||
License: "MIT"
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010-2026 Google LLC. https://angular.dev/license
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Package: @angular/core
|
||||
License: "MIT"
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010-2026 Google LLC. https://angular.dev/license
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Package: rxjs
|
||||
License: "Apache-2.0"
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Package: tslib
|
||||
License: "0BSD"
|
||||
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
--------------------------------------------------------------------------------
|
||||
Package: @angular/common
|
||||
License: "MIT"
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010-2026 Google LLC. https://angular.dev/license
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Package: @angular/platform-browser
|
||||
License: "MIT"
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010-2026 Google LLC. https://angular.dev/license
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Package: @angular/router
|
||||
License: "MIT"
|
||||
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2010-2026 Google LLC. https://angular.dev/license
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
BIN
dist/favicon.ico
vendored
BIN
dist/favicon.ico
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 15 KiB |
13
dist/index.html
vendored
13
dist/index.html
vendored
@@ -1,17 +1,18 @@
|
||||
<!doctype html>
|
||||
<html lang="ru" data-beasties-container>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Оплата через СБП</title>
|
||||
<title>fastCHECK</title>
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
|
||||
<meta name="theme-color" content="#2563eb">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="default">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<style>*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body{height:100%}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#1e40af}</style><link rel="stylesheet" href="styles-4STSJS4C.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-4STSJS4C.css"></noscript></head>
|
||||
<link rel="icon" type="image/png" href="logo_small.png">
|
||||
<link rel="apple-touch-icon" href="logo_small.png">
|
||||
<link rel="stylesheet" href="styles.css"></head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
<link rel="modulepreload" href="chunk-FBABAKVO.js"><script src="main-XKBOOIAP.js" type="module"></script></body>
|
||||
<link rel="modulepreload" href="chunk-XQ4WH5CY.js"><script src="main.js" type="module"></script></body>
|
||||
</html>
|
||||
|
||||
1
dist/styles-4STSJS4C.css
vendored
1
dist/styles-4STSJS4C.css
vendored
@@ -1 +0,0 @@
|
||||
*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body{height:100%}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background:#1e40af}
|
||||
73
public/i18n/en.json
Normal file
73
public/i18n/en.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"header": {
|
||||
"nav_about": "About",
|
||||
"nav_contacts": "Contacts",
|
||||
"nav_support": "Support",
|
||||
"aria_nav": "Navigation",
|
||||
"aria_menu": "Mobile menu",
|
||||
"aria_burger": "Menu"
|
||||
},
|
||||
"footer": {
|
||||
"desc": "An innovative virtual check service for individuals. Create digital checks online and cash them out at partner bank ATMs 24/7.",
|
||||
"contacts_heading": "Contacts",
|
||||
"russia": "Russia",
|
||||
"armenia": "Armenia",
|
||||
"support_label": "Tech support",
|
||||
"support_hours": "24/7",
|
||||
"questions_label": "Questions",
|
||||
"questions_hours": "10:00–19:00 MSK",
|
||||
"legal_heading": "Legal details",
|
||||
"legal_company": "LLC «VIAEXPORT»",
|
||||
"legal_inn_ru": "TIN (RU): 9909675800",
|
||||
"legal_inn_am": "TIN (AM): 01051049",
|
||||
"legal_kpp": "KPP: 770287001",
|
||||
"legal_ogrn": "OGRN: 282.110.1296681",
|
||||
"legal_address": "Armenia, 0201, Yerevan, Minskaya St. 21-23, apt. 44",
|
||||
"rights": "LLC «VIAEXPORT». All rights reserved.",
|
||||
"director": "Director: Amirkhanyan Sargis Artashesovich"
|
||||
},
|
||||
"fastcheck": {
|
||||
"subtitle": "Enter fastCHECK details or create a new one",
|
||||
"number_label": "fastCHECK number",
|
||||
"number_placeholder": "1234-5678-0001",
|
||||
"number_new": "New",
|
||||
"amount_label": "Amount",
|
||||
"amount_checking": "Checking…",
|
||||
"code_label": "Code",
|
||||
"code_placeholder": "00000",
|
||||
"pay_btn": "Pay",
|
||||
"modal_title": "Sign in via Telegram",
|
||||
"modal_sub": "Scan QR or open the link",
|
||||
"modal_loading": "Loading…",
|
||||
"modal_open_tg": "Open in Telegram",
|
||||
"modal_confirming": "Confirming payment…",
|
||||
"modal_waiting": "Waiting for sign-in…",
|
||||
"modal_paid_title": "Paid",
|
||||
"modal_paid_sub": "fastCHECK successfully accepted."
|
||||
},
|
||||
"create": {
|
||||
"title": "New",
|
||||
"subtitle": "Enter the amount to top up",
|
||||
"back_label": "Back",
|
||||
"payment_label": "Payment method",
|
||||
"currency_label": "Currency",
|
||||
"amount_label": "Payment amount",
|
||||
"note_label": "Note",
|
||||
"note_placeholder": "Reason for payment...",
|
||||
"creating": "Creating…",
|
||||
"create_btn": "Create"
|
||||
},
|
||||
"sbp": {
|
||||
"title": "Pay via SBP",
|
||||
"subtitle": "Fast Payment System",
|
||||
"amount_label": "Payment amount",
|
||||
"currency_name": "Russian ruble",
|
||||
"note_label": "Note",
|
||||
"note_placeholder": "Reason for payment...",
|
||||
"pay_loading": "Please wait...",
|
||||
"pay_btn": "Proceed to payment"
|
||||
},
|
||||
"common": {
|
||||
"secure": "Secure connection"
|
||||
}
|
||||
}
|
||||
73
public/i18n/hy.json
Normal file
73
public/i18n/hy.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"header": {
|
||||
"nav_about": "Ծառայության մասին",
|
||||
"nav_contacts": "Կապ",
|
||||
"nav_support": "Աջակցություն",
|
||||
"aria_nav": "Նավիգացիա",
|
||||
"aria_menu": "Բջջային ընտրացանկ",
|
||||
"aria_burger": "Ընտրացանկ"
|
||||
},
|
||||
"footer": {
|
||||
"desc": "Ֆիզիկական անձանց համար վիրտուալ չեկերի նորարարական ծառայություն: Ստեղծեք թվային չեկեր առցանց և կանխիկացրեք դրանք գործընկեր բանկերի բանկոմատներում 24/7:",
|
||||
"contacts_heading": "Կապ",
|
||||
"russia": "Ռուսաստան",
|
||||
"armenia": "Հայաստան",
|
||||
"support_label": "Տեխ. աջակցություն",
|
||||
"support_hours": "24/7",
|
||||
"questions_label": "Հարցեր",
|
||||
"questions_hours": "10:00–19:00 MSK",
|
||||
"legal_heading": "Իրավաբանական տվյալներ",
|
||||
"legal_company": "ООО «ВИАЭКСПОРТ»",
|
||||
"legal_inn_ru": "ИНН (РФ): 9909675800",
|
||||
"legal_inn_am": "ИНН (AM): 01051049",
|
||||
"legal_kpp": "КПП: 770287001",
|
||||
"legal_ogrn": "ОГРН: 282.110.1296681",
|
||||
"legal_address": "Հայաստան, 0201, Երևան, Մինսկայա փ. 21-23, բն. 44",
|
||||
"rights": "ООО «ВИАЭКСПОРТ»: Բոլոր իրավունքները պաշտպանված են:",
|
||||
"director": "Տնօրեն՝ Ամիրխանյան Սարգիս Արտաշեսի"
|
||||
},
|
||||
"fastcheck": {
|
||||
"subtitle": "Մուտքագրեք fastCHECK տվյալները կամ ստեղծեք նորը",
|
||||
"number_label": "fastCHECK համար",
|
||||
"number_placeholder": "1234-5678-0001",
|
||||
"number_new": "Նոր",
|
||||
"amount_label": "Գումար",
|
||||
"amount_checking": "Ստուգվում է…",
|
||||
"code_label": "Կոդ",
|
||||
"code_placeholder": "00000",
|
||||
"pay_btn": "Վճարել",
|
||||
"modal_title": "Մուտք գործել Telegram-ով",
|
||||
"modal_sub": "Սկանավորեք QR կամ բացեք հղումը",
|
||||
"modal_loading": "Բեռնվում է…",
|
||||
"modal_open_tg": "Բացել Telegram-ում",
|
||||
"modal_confirming": "Վճարման հաստատում…",
|
||||
"modal_waiting": "Սպասում ենք մուտքի…",
|
||||
"modal_paid_title": "Վճարված է",
|
||||
"modal_paid_sub": "fastCHECK-ը հաջողությամբ ընդունված է:"
|
||||
},
|
||||
"create": {
|
||||
"title": "Նոր",
|
||||
"subtitle": "Նշեք համալրման գումարը",
|
||||
"back_label": "Հետ",
|
||||
"payment_label": "Վճարման եղանակ",
|
||||
"currency_label": "Արժույթ",
|
||||
"amount_label": "Վճարման գումար",
|
||||
"note_label": "Նշում",
|
||||
"note_placeholder": "Վճարման պատճառ...",
|
||||
"creating": "Ստեղծվում է…",
|
||||
"create_btn": "Ստեղծել"
|
||||
},
|
||||
"sbp": {
|
||||
"title": "Վճարել SBP-ով",
|
||||
"subtitle": "Արագ վճարումների համակարգ",
|
||||
"amount_label": "Վճարման գումար",
|
||||
"currency_name": "Ռուսական ռուբլի",
|
||||
"note_label": "Նշում",
|
||||
"note_placeholder": "Վճարման պատճառ...",
|
||||
"pay_loading": "Սպասեք...",
|
||||
"pay_btn": "Անցնել վճարմանը"
|
||||
},
|
||||
"common": {
|
||||
"secure": "Անվտանգ կապ"
|
||||
}
|
||||
}
|
||||
73
public/i18n/ru.json
Normal file
73
public/i18n/ru.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"header": {
|
||||
"nav_about": "О сервисе",
|
||||
"nav_contacts": "Контакты",
|
||||
"nav_support": "Поддержка",
|
||||
"aria_nav": "Навигация",
|
||||
"aria_menu": "Мобильное меню",
|
||||
"aria_burger": "Меню"
|
||||
},
|
||||
"footer": {
|
||||
"desc": "Инновационный сервис виртуальных чеков для физических лиц. Создавайте цифровые чеки онлайн и обналичивайте их через банкоматы банков-партнёров 24/7.",
|
||||
"contacts_heading": "Контакты",
|
||||
"russia": "Россия",
|
||||
"armenia": "Армения",
|
||||
"support_label": "Техподдержка",
|
||||
"support_hours": "24/7",
|
||||
"questions_label": "Вопросы",
|
||||
"questions_hours": "10:00–19:00 МСК",
|
||||
"legal_heading": "Реквизиты",
|
||||
"legal_company": "ООО «ВИАЭКСПОРТ»",
|
||||
"legal_inn_ru": "ИНН (РФ): 9909675800",
|
||||
"legal_inn_am": "ИНН (AM): 01051049",
|
||||
"legal_kpp": "КПП: 770287001",
|
||||
"legal_ogrn": "ОГРН: 282.110.1296681",
|
||||
"legal_address": "Армения, 0201, Ереван, ул. Минская, дом 21-23, кв. 44",
|
||||
"rights": "ООО «ВИАЭКСПОРТ». Все права защищены.",
|
||||
"director": "Директор: Амирханян Саргис Арташесович"
|
||||
},
|
||||
"fastcheck": {
|
||||
"subtitle": "Введите данные fastCHECK или создайте новый",
|
||||
"number_label": "Номер fastCHECK",
|
||||
"number_placeholder": "1234-5678-0001",
|
||||
"number_new": "Новый",
|
||||
"amount_label": "Сумма",
|
||||
"amount_checking": "Проверяем…",
|
||||
"code_label": "Код",
|
||||
"code_placeholder": "00000",
|
||||
"pay_btn": "Оплатить",
|
||||
"modal_title": "Войти через Telegram",
|
||||
"modal_sub": "Отсканируйте QR или откройте ссылку",
|
||||
"modal_loading": "Загрузка…",
|
||||
"modal_open_tg": "Открыть в Telegram",
|
||||
"modal_confirming": "Подтверждение оплаты…",
|
||||
"modal_waiting": "Ожидание входа…",
|
||||
"modal_paid_title": "Оплачено",
|
||||
"modal_paid_sub": "fastCHECK успешно принят."
|
||||
},
|
||||
"create": {
|
||||
"title": "Новый",
|
||||
"subtitle": "Укажите сумму для пополнения",
|
||||
"back_label": "Назад",
|
||||
"payment_label": "Способ оплаты",
|
||||
"currency_label": "Валюта",
|
||||
"amount_label": "Сумма платежа",
|
||||
"note_label": "Примечание",
|
||||
"note_placeholder": "Причина платежа...",
|
||||
"creating": "Создание…",
|
||||
"create_btn": "Создать"
|
||||
},
|
||||
"sbp": {
|
||||
"title": "Оплата через СБП",
|
||||
"subtitle": "Система быстрых платежей",
|
||||
"amount_label": "Сумма платежа",
|
||||
"currency_name": "Российский рубль",
|
||||
"note_label": "Примечание",
|
||||
"note_placeholder": "Причина платежа...",
|
||||
"pay_loading": "Подождите...",
|
||||
"pay_btn": "Перейти к оплате"
|
||||
},
|
||||
"common": {
|
||||
"secure": "Защищённое соединение"
|
||||
}
|
||||
}
|
||||
@@ -1 +1,5 @@
|
||||
<router-outlet />
|
||||
<app-site-header />
|
||||
<main class="app-main">
|
||||
<router-outlet />
|
||||
</main>
|
||||
<app-site-footer />
|
||||
@@ -1,2 +1,12 @@
|
||||
:host { display: block; min-height: 100dvh; }
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100dvh;
|
||||
}
|
||||
|
||||
.app-main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
import { SiteHeader } from './site-header/site-header';
|
||||
import { SiteFooter } from './site-footer/site-footer';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
imports: [RouterOutlet],
|
||||
imports: [RouterOutlet, SiteHeader, SiteFooter],
|
||||
templateUrl: './app.html',
|
||||
styleUrl: './app.scss'
|
||||
})
|
||||
|
||||
@@ -2,24 +2,24 @@
|
||||
<div class="card">
|
||||
|
||||
<div class="card__header">
|
||||
<a class="back" routerLink="/" aria-label="Назад">
|
||||
<a class="back" routerLink="/" [attr.aria-label]="'create.back_label' | translate">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 18l-6-6 6-6" />
|
||||
</svg>
|
||||
</a>
|
||||
<h1 class="card__title">
|
||||
Новый
|
||||
{{ 'create.title' | translate }}
|
||||
<span class="brand"><span class="brand__fast">fast</span><span class="brand__check">CHECK</span></span>
|
||||
</h1>
|
||||
<p class="card__subtitle">Укажите сумму для пополнения</p>
|
||||
<p class="card__subtitle">{{ 'create.subtitle' | translate }}</p>
|
||||
</div>
|
||||
|
||||
<div class="card__body">
|
||||
|
||||
<!-- Payment methods -->
|
||||
<div class="field">
|
||||
<span class="field__label">Способ оплаты</span>
|
||||
<span class="field__label">{{ 'create.payment_label' | translate }}</span>
|
||||
<div class="methods">
|
||||
<button type="button" class="method" [class.method--active]="payment() === 'sbp'"
|
||||
(click)="selectPayment('sbp', true)" aria-label="СБП">
|
||||
@@ -41,31 +41,26 @@
|
||||
|
||||
<!-- Currencies -->
|
||||
<div class="field">
|
||||
<span class="field__label">Валюта</span>
|
||||
<span class="field__label">{{ 'create.currency_label' | translate }}</span>
|
||||
<div class="currencies">
|
||||
<button type="button" class="chip" [class.chip--active]="currency() === 'RUB'"
|
||||
(click)="selectCurrency('RUB', true)">
|
||||
<!-- <span class="chip__flag">🇷🇺</span> -->
|
||||
<span class="chip__sign">₽</span>
|
||||
<span class="chip__code">RUB</span>
|
||||
</button>
|
||||
<button type="button" class="chip chip--disabled" disabled>
|
||||
<!-- <span class="chip__flag">🇨🇳</span> -->
|
||||
<span class="chip__sign">¥</span>
|
||||
<span class="chip__code">CNY</span>
|
||||
</button>
|
||||
<button type="button" class="chip chip--disabled" disabled>
|
||||
<!-- <span class="chip__flag">🇺🇸</span> -->
|
||||
<span class="chip__sign">$</span>
|
||||
<span class="chip__code">USD</span>
|
||||
</button>
|
||||
<button type="button" class="chip chip--disabled" disabled>
|
||||
<!-- <span class="chip__flag">🇪🇺</span> -->
|
||||
<span class="chip__sign">€</span>
|
||||
<span class="chip__code">EUR</span>
|
||||
</button>
|
||||
<button type="button" class="chip chip--disabled" disabled>
|
||||
<!-- <span class="chip__flag">🇦🇲</span> -->
|
||||
<span class="chip__sign">֏</span>
|
||||
<span class="chip__code">AMD</span>
|
||||
</button>
|
||||
@@ -73,7 +68,7 @@
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="field__label" for="amount">Сумма платежа</label>
|
||||
<label class="field__label" for="amount">{{ 'create.amount_label' | translate }}</label>
|
||||
<div class="input-wrap" [class.input-wrap--error]="error()">
|
||||
<span class="input-wrap__prefix">₽</span>
|
||||
<input
|
||||
@@ -95,13 +90,13 @@
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="field__label" for="note">Примечание</label>
|
||||
<label class="field__label" for="note">{{ 'create.note_label' | translate }}</label>
|
||||
<textarea
|
||||
id="note"
|
||||
class="note-input"
|
||||
[ngModel]="note()"
|
||||
(ngModelChange)="onNoteChange($event)"
|
||||
placeholder="Причина платежа..."
|
||||
[placeholder]="'create.note_placeholder' | translate"
|
||||
rows="3"
|
||||
maxlength="500"
|
||||
></textarea>
|
||||
@@ -115,9 +110,9 @@
|
||||
</svg>
|
||||
</span>
|
||||
@if (loading()) {
|
||||
Создание…
|
||||
{{ 'create.creating' | translate }}
|
||||
} @else {
|
||||
Создать
|
||||
{{ 'create.create_btn' | translate }}
|
||||
<span class="brand"><span class="brand__fast">fast</span><span class="brand__check">CHECK</span></span>
|
||||
}
|
||||
</button>
|
||||
@@ -129,7 +124,7 @@
|
||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
||||
</svg>
|
||||
Защищённое соединение
|
||||
{{ 'common.secure' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Router, RouterLink } from '@angular/router';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { FastcheckService } from '../../fastcheck.service';
|
||||
import { FASTCHECK_API } from '../../api';
|
||||
import { TranslatePipe } from '../../translate/translate.pipe';
|
||||
|
||||
interface CreateFastcheckResponse {
|
||||
fastcheck: string;
|
||||
@@ -17,7 +18,7 @@ type Currency = 'RUB' | 'CNY' | 'USD' | 'EUR' | 'AMD';
|
||||
|
||||
@Component({
|
||||
selector: 'app-create-page',
|
||||
imports: [FormsModule, RouterLink],
|
||||
imports: [FormsModule, RouterLink, TranslatePipe],
|
||||
templateUrl: './create-page.html',
|
||||
styleUrl: './create-page.scss'
|
||||
})
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
<img class="card__brand" src="/logo_big.png"
|
||||
alt="fastCHECK" width="220" height="60" />
|
||||
<p class="card__subtitle">
|
||||
Введите данные
|
||||
<span class="brand"><span class="brand__fast">fast</span><span class="brand__check">CHECK</span></span>
|
||||
или создайте новый
|
||||
{{ 'fastcheck.subtitle' | translate }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -16,8 +14,7 @@
|
||||
<!-- Fastcheck number + new -->
|
||||
<div class="field">
|
||||
<label class="field__label" for="fcNumber">
|
||||
Номер
|
||||
<span class="brand"><span class="brand__fast">fast</span><span class="brand__check">CHECK</span></span>
|
||||
{{ 'fastcheck.number_label' | translate }}
|
||||
</label>
|
||||
<div class="row">
|
||||
<input
|
||||
@@ -26,18 +23,18 @@
|
||||
class="input"
|
||||
[ngModel]="fastcheckNumber()"
|
||||
(ngModelChange)="onNumberChange($event)"
|
||||
placeholder="1234-5678-0001"
|
||||
[placeholder]="'fastcheck.number_placeholder' | translate"
|
||||
inputmode="numeric"
|
||||
autocomplete="off"
|
||||
maxlength="14"
|
||||
/>
|
||||
<a class="btn btn--ghost" routerLink="/new" aria-label="Создать новый fastCHECK">Новый</a>
|
||||
<a class="btn btn--ghost" routerLink="/new" aria-label="Создать новый fastCHECK">{{ 'fastcheck.number_new' | translate }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Amount -->
|
||||
<div class="field">
|
||||
<label class="field__label" for="fcAmount">Сумма</label>
|
||||
<label class="field__label" for="fcAmount">{{ 'fastcheck.amount_label' | translate }}</label>
|
||||
<div class="input-wrap">
|
||||
<span class="input-wrap__prefix">₽</span>
|
||||
<input
|
||||
@@ -54,20 +51,20 @@
|
||||
/>
|
||||
</div>
|
||||
@if (amountLoading()) {
|
||||
<span class="field__hint">Проверяем…</span>
|
||||
<span class="field__hint">{{ 'fastcheck.amount_checking' | translate }}</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Code -->
|
||||
<div class="field">
|
||||
<label class="field__label" for="fcCode">Код</label>
|
||||
<label class="field__label" for="fcCode">{{ 'fastcheck.code_label' | translate }}</label>
|
||||
<input
|
||||
id="fcCode"
|
||||
type="text"
|
||||
class="input"
|
||||
[ngModel]="fastcheckCode()"
|
||||
(ngModelChange)="onCodeChange($event)"
|
||||
placeholder="00000"
|
||||
[placeholder]="'fastcheck.code_placeholder' | translate"
|
||||
inputmode="numeric"
|
||||
maxlength="5"
|
||||
autocomplete="one-time-code"
|
||||
@@ -85,7 +82,7 @@
|
||||
<line x1="1" y1="10" x2="23" y2="10" />
|
||||
</svg>
|
||||
</span>
|
||||
Оплатить
|
||||
{{ 'fastcheck.pay_btn' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -95,7 +92,7 @@
|
||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
||||
</svg>
|
||||
Защищённое соединение
|
||||
{{ 'common.secure' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -113,21 +110,21 @@
|
||||
stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M20 6L9 17l-5-5" />
|
||||
</svg>
|
||||
<h2 class="modal__title">Оплачено</h2>
|
||||
<h2 class="modal__title">{{ 'fastcheck.modal_paid_title' | translate }}</h2>
|
||||
<p class="modal__sub">
|
||||
<span class="brand"><span class="brand__fast">fast</span><span class="brand__check">CHECK</span></span>
|
||||
успешно принят.
|
||||
{{ 'fastcheck.modal_paid_sub' | translate }}
|
||||
</p>
|
||||
</div>
|
||||
} @else {
|
||||
<img class="brand-logo brand-logo--small" src="/logo_small.png"
|
||||
alt="fastCHECK" width="32" height="32" />
|
||||
<h2 class="modal__title">Войти через Telegram</h2>
|
||||
<p class="modal__sub">Отсканируйте QR или откройте ссылку</p>
|
||||
<h2 class="modal__title">{{ 'fastcheck.modal_title' | translate }}</h2>
|
||||
<p class="modal__sub">{{ 'fastcheck.modal_sub' | translate }}</p>
|
||||
|
||||
<div class="qr">
|
||||
@if (popupLoading() && !webSessionId()) {
|
||||
<div class="qr__placeholder">Загрузка…</div>
|
||||
<div class="qr__placeholder">{{ 'fastcheck.modal_loading' | translate }}</div>
|
||||
} @else if (webSessionId()) {
|
||||
<img [src]="qrUrl()" width="240" height="240" alt="QR Telegram" />
|
||||
}
|
||||
@@ -138,14 +135,14 @@
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path d="M9.04 15.65l-.36 4.06c.51 0 .73-.22.99-.48l2.38-2.27 4.93 3.6c.9.5 1.55.24 1.79-.83l3.24-15.18h.01c.29-1.34-.48-1.86-1.36-1.54L1.13 9.66c-1.32.5-1.3 1.23-.22 1.56l4.92 1.53L17.27 5.6c.54-.34 1.03-.15.62.19" />
|
||||
</svg>
|
||||
Открыть в Telegram
|
||||
{{ 'fastcheck.modal_open_tg' | translate }}
|
||||
</a>
|
||||
}
|
||||
|
||||
@if (popupLoading() && webSessionId()) {
|
||||
<p class="modal__hint">Подтверждение оплаты…</p>
|
||||
<p class="modal__hint">{{ 'fastcheck.modal_confirming' | translate }}</p>
|
||||
} @else if (webSessionId()) {
|
||||
<p class="modal__hint">Ожидание входа…</p>
|
||||
<p class="modal__hint">{{ 'fastcheck.modal_waiting' | translate }}</p>
|
||||
}
|
||||
|
||||
@if (popupError()) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Router, RouterLink } from '@angular/router';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { FastcheckService } from '../../fastcheck.service';
|
||||
import { FASTCHECK_API } from '../../api';
|
||||
import { TranslatePipe } from '../../translate/translate.pipe';
|
||||
|
||||
interface WebSessionResponse {
|
||||
sessionId: string;
|
||||
@@ -22,7 +23,7 @@ interface CheckFastcheckResponse {
|
||||
|
||||
@Component({
|
||||
selector: 'app-fastcheck-page',
|
||||
imports: [FormsModule, RouterLink],
|
||||
imports: [FormsModule, RouterLink, TranslatePipe],
|
||||
templateUrl: './fastcheck-page.html',
|
||||
styleUrl: './fastcheck-page.scss'
|
||||
})
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
<img src="https://sbp.nspk.ru/storage/settings/common/logo/0645d335-8b62-43a1-9a33-0d4c9d1dc0e0.svg"
|
||||
alt="СБП" />
|
||||
</div>
|
||||
<h1 class="card__title">Оплата через СБП</h1>
|
||||
<p class="card__subtitle">Система быстрых платежей</p>
|
||||
<h1 class="card__title">{{ 'sbp.title' | translate }}</h1>
|
||||
<p class="card__subtitle">{{ 'sbp.subtitle' | translate }}</p>
|
||||
</div>
|
||||
|
||||
<div class="card__body">
|
||||
|
||||
<div class="field">
|
||||
<label class="field__label" for="amount">Сумма платежа</label>
|
||||
<label class="field__label" for="amount">{{ 'sbp.amount_label' | translate }}</label>
|
||||
<div class="input-wrap" [class.input-wrap--error]="error()">
|
||||
<span class="input-wrap__prefix">₽</span>
|
||||
<input
|
||||
@@ -37,17 +37,17 @@
|
||||
<div class="currency-badge">
|
||||
<span class="currency-badge__flag">🇷🇺</span>
|
||||
<span class="currency-badge__code">RUB</span>
|
||||
<span class="currency-badge__name">Российский рубль</span>
|
||||
<span class="currency-badge__name">{{ 'sbp.currency_name' | translate }}</span>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<label class="field__label" for="note">Примечание</label>
|
||||
<label class="field__label" for="note">{{ 'sbp.note_label' | translate }}</label>
|
||||
<textarea
|
||||
id="note"
|
||||
class="note-input"
|
||||
[ngModel]="note()"
|
||||
(ngModelChange)="onNoteChange($event)"
|
||||
placeholder="Причина платежа..."
|
||||
[placeholder]="'sbp.note_placeholder' | translate"
|
||||
rows="3"
|
||||
maxlength="500"
|
||||
></textarea>
|
||||
@@ -61,7 +61,11 @@
|
||||
<line x1="1" y1="10" x2="23" y2="10" />
|
||||
</svg>
|
||||
</span>
|
||||
{{ loading() ? 'Подождите...' : 'Перейти к оплате' }}
|
||||
@if (loading()) {
|
||||
{{ 'sbp.pay_loading' | translate }}
|
||||
} @else {
|
||||
{{ 'sbp.pay_btn' | translate }}
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -71,7 +75,7 @@
|
||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
||||
</svg>
|
||||
Защищённое соединение
|
||||
{{ 'common.secure' | translate }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component, computed, inject, signal } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { TranslatePipe } from '../../translate/translate.pipe';
|
||||
|
||||
interface LegacyPayResponse {
|
||||
payload?: string;
|
||||
@@ -17,7 +18,7 @@ interface LegacyPayResponse {
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-legacy-pay-page',
|
||||
imports: [FormsModule],
|
||||
imports: [FormsModule, TranslatePipe],
|
||||
templateUrl: './legacy-pay-page.html',
|
||||
styleUrl: './legacy-pay-page.scss'
|
||||
})
|
||||
|
||||
57
src/app/site-footer/site-footer.html
Normal file
57
src/app/site-footer/site-footer.html
Normal file
@@ -0,0 +1,57 @@
|
||||
<footer class="site-footer">
|
||||
<div class="site-footer__inner">
|
||||
|
||||
<!-- Brand + about -->
|
||||
<div class="site-footer__col site-footer__col--brand">
|
||||
<a class="site-footer__brand" href="/">
|
||||
<!-- <img src="/logo_big.png" alt="fastCHECK" width="28" height="28" /> -->
|
||||
<span class="site-footer__wordmark">
|
||||
<span class="wm-fast">fast</span><span class="wm-check">CHECK</span>
|
||||
</span>
|
||||
</a>
|
||||
<p class="site-footer__desc" id="about">{{ 'footer.desc' | translate }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Contacts -->
|
||||
<div class="site-footer__col" id="contacts">
|
||||
<h3 class="site-footer__heading">{{ 'footer.contacts_heading' | translate }}</h3>
|
||||
<ul class="site-footer__list">
|
||||
<li>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.07 10.5a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L7.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 21 16.92z"/></svg>
|
||||
<a href="tel:+79299037443">+7 (929) 903-74-43</a> <span class="site-footer__note">{{ 'footer.russia' | translate }}</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.07 10.5a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L7.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 21 16.92z"/></svg>
|
||||
<a href="tel:+37498632421">+374 98 632421</a> <span class="site-footer__note">{{ 'footer.armenia' | translate }}</span>
|
||||
</li>
|
||||
<li>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></svg>
|
||||
<a href="mailto:info@viaexport.store">info@viaexport.store</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="site-footer__hours">
|
||||
<p><strong>{{ 'footer.support_label' | translate }}:</strong> {{ 'footer.support_hours' | translate }}</p>
|
||||
<p><strong>{{ 'footer.questions_label' | translate }}:</strong> {{ 'footer.questions_hours' | translate }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Legal -->
|
||||
<div class="site-footer__col">
|
||||
<h3 class="site-footer__heading">{{ 'footer.legal_heading' | translate }}</h3>
|
||||
<ul class="site-footer__list site-footer__list--legal">
|
||||
<li>{{ 'footer.legal_company' | translate }}</li>
|
||||
<li>{{ 'footer.legal_inn_ru' | translate }}</li>
|
||||
<li>{{ 'footer.legal_inn_am' | translate }}</li>
|
||||
<li>{{ 'footer.legal_kpp' | translate }}</li>
|
||||
<li>{{ 'footer.legal_ogrn' | translate }}</li>
|
||||
<li class="site-footer__address">{{ 'footer.legal_address' | translate }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="site-footer__bottom">
|
||||
<p>© {{ year }} {{ 'footer.rights' | translate }}</p>
|
||||
<p>{{ 'footer.director' | translate }}</p>
|
||||
</div>
|
||||
</footer>
|
||||
156
src/app/site-footer/site-footer.scss
Normal file
156
src/app/site-footer/site-footer.scss
Normal file
@@ -0,0 +1,156 @@
|
||||
:host { display: block; }
|
||||
|
||||
.site-footer {
|
||||
background: #0f172a;
|
||||
color: #94a3b8;
|
||||
|
||||
&__inner {
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
padding: 48px 24px 32px;
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr 1fr;
|
||||
gap: 40px;
|
||||
|
||||
@media (max-width: 860px) {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 32px;
|
||||
padding: 36px 20px 24px;
|
||||
}
|
||||
}
|
||||
|
||||
&__col {
|
||||
&--brand {
|
||||
@media (max-width: 860px) {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
text-decoration: none;
|
||||
margin-bottom: 14px;
|
||||
|
||||
img {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
object-fit: contain;
|
||||
filter: brightness(0) invert(1);
|
||||
opacity: 0.9;
|
||||
}
|
||||
}
|
||||
|
||||
&__wordmark {
|
||||
font-size: 18px;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
&__desc {
|
||||
font-size: 13.5px;
|
||||
line-height: 1.65;
|
||||
color: #64748b;
|
||||
max-width: 380px;
|
||||
}
|
||||
|
||||
&__heading {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.8px;
|
||||
color: #e2e8f0;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
&__list {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
margin-bottom: 18px;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 13.5px;
|
||||
|
||||
svg { flex-shrink: 0; opacity: 0.5; }
|
||||
}
|
||||
|
||||
a {
|
||||
color: #94a3b8;
|
||||
text-decoration: none;
|
||||
transition: color 0.15s;
|
||||
|
||||
&:hover { color: #e2e8f0; }
|
||||
}
|
||||
|
||||
&--legal {
|
||||
li {
|
||||
display: block;
|
||||
font-size: 12.5px;
|
||||
color: #64748b;
|
||||
gap: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__note {
|
||||
font-size: 11px;
|
||||
color: #475569;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
&__hours {
|
||||
font-size: 12.5px;
|
||||
color: #64748b;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
&__address {
|
||||
color: #475569;
|
||||
font-size: 12px !important;
|
||||
line-height: 1.5;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
&__bottom {
|
||||
border-top: 1px solid #1e293b;
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
padding: 16px 24px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px 24px;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
color: #475569;
|
||||
|
||||
@media (max-width: 560px) {
|
||||
flex-direction: column;
|
||||
padding: 14px 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wm-fast {
|
||||
font-weight: 400;
|
||||
font-size: 0.72em;
|
||||
color: #64748b;
|
||||
margin-right: 0.04em;
|
||||
}
|
||||
.wm-check {
|
||||
font-weight: 700;
|
||||
font-size: 1em;
|
||||
color: #93c5fd;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
12
src/app/site-footer/site-footer.ts
Normal file
12
src/app/site-footer/site-footer.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { TranslatePipe } from '../translate/translate.pipe';
|
||||
|
||||
@Component({
|
||||
selector: 'app-site-footer',
|
||||
imports: [TranslatePipe],
|
||||
templateUrl: './site-footer.html',
|
||||
styleUrl: './site-footer.scss'
|
||||
})
|
||||
export class SiteFooter {
|
||||
year = new Date().getFullYear();
|
||||
}
|
||||
58
src/app/site-header/site-header.html
Normal file
58
src/app/site-header/site-header.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<header class="site-header">
|
||||
<div class="site-header__inner">
|
||||
|
||||
<!-- Brand -->
|
||||
<a class="site-header__brand" routerLink="/" (click)="closeMenu()">
|
||||
<img src="/logo_small.png" alt="fastCHECK" width="32" height="32" />
|
||||
<span class="site-header__wordmark">
|
||||
<span class="wm-fast">fast</span><span class="wm-check">CHECK</span>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<!-- Desktop nav -->
|
||||
<nav class="site-header__nav" [attr.aria-label]="'header.aria_nav' | translate">
|
||||
<a class="site-header__link" href="#about">{{ 'header.nav_about' | translate }}</a>
|
||||
<a class="site-header__link" href="#contacts">{{ 'header.nav_contacts' | translate }}</a>
|
||||
<a class="site-header__link" href="mailto:info@viaexport.store">{{ 'header.nav_support' | translate }}</a>
|
||||
</nav>
|
||||
|
||||
<!-- Language switcher -->
|
||||
<div class="site-header__langs">
|
||||
<button type="button" class="site-header__lang" [class.site-header__lang--active]="currentLang() === 'ru'" (click)="setLang('ru')">RU</button>
|
||||
<button type="button" class="site-header__lang" [class.site-header__lang--active]="currentLang() === 'en'" (click)="setLang('en')">EN</button>
|
||||
<button type="button" class="site-header__lang" [class.site-header__lang--active]="currentLang() === 'hy'" (click)="setLang('hy')">HY</button>
|
||||
</div>
|
||||
|
||||
<!-- Mobile hamburger -->
|
||||
<button class="site-header__burger" type="button"
|
||||
[attr.aria-expanded]="menuOpen()"
|
||||
[attr.aria-label]="'header.aria_burger' | translate"
|
||||
(click)="toggleMenu()">
|
||||
@if (menuOpen()) {
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="2.5" stroke-linecap="round">
|
||||
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
||||
</svg>
|
||||
} @else {
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="2.5" stroke-linecap="round">
|
||||
<line x1="3" y1="7" x2="21" y2="7"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="17" x2="21" y2="17"/>
|
||||
</svg>
|
||||
}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Mobile dropdown -->
|
||||
@if (menuOpen()) {
|
||||
<nav class="site-header__mobile-menu" (click)="closeMenu()" [attr.aria-label]="'header.aria_menu' | translate">
|
||||
<a class="site-header__mobile-link" href="#about">{{ 'header.nav_about' | translate }}</a>
|
||||
<a class="site-header__mobile-link" href="#contacts">{{ 'header.nav_contacts' | translate }}</a>
|
||||
<a class="site-header__mobile-link" href="mailto:info@viaexport.store">{{ 'header.nav_support' | translate }}</a>
|
||||
<div class="site-header__mobile-langs">
|
||||
<button type="button" class="site-header__lang" [class.site-header__lang--active]="currentLang() === 'ru'" (click)="setLang('ru')">RU</button>
|
||||
<button type="button" class="site-header__lang" [class.site-header__lang--active]="currentLang() === 'en'" (click)="setLang('en')">EN</button>
|
||||
<button type="button" class="site-header__lang" [class.site-header__lang--active]="currentLang() === 'hy'" (click)="setLang('hy')">HY</button>
|
||||
</div>
|
||||
</nav>
|
||||
}
|
||||
</header>
|
||||
169
src/app/site-header/site-header.scss
Normal file
169
src/app/site-header/site-header.scss
Normal file
@@ -0,0 +1,169 @@
|
||||
:host {
|
||||
display: block;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 900;
|
||||
}
|
||||
|
||||
.site-header {
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
box-shadow: 0 1px 8px rgba(0, 0, 0, 0.06);
|
||||
|
||||
&__inner {
|
||||
max-width: 1100px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 32px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
padding: 0 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&__brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
text-decoration: none;
|
||||
flex-shrink: 0;
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
&__wordmark {
|
||||
font-size: 18px;
|
||||
letter-spacing: -0.02em;
|
||||
white-space: nowrap;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
&__nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-left: auto;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__link {
|
||||
padding: 8px 14px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #475569;
|
||||
text-decoration: none;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
|
||||
&:hover {
|
||||
background: #f1f5f9;
|
||||
color: #0f172a;
|
||||
}
|
||||
}
|
||||
|
||||
&__langs {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
margin-left: 8px;
|
||||
|
||||
@media (max-width: 600px) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__lang {
|
||||
padding: 5px 8px;
|
||||
border-radius: 6px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.04em;
|
||||
color: #94a3b8;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
font-family: inherit;
|
||||
|
||||
&:hover { background: #f1f5f9; color: #475569; }
|
||||
|
||||
&--active {
|
||||
background: #eff6ff;
|
||||
color: #1e40af;
|
||||
}
|
||||
}
|
||||
|
||||
&__mobile-langs {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
padding: 8px 14px 4px;
|
||||
}
|
||||
|
||||
&__burger {
|
||||
display: none;
|
||||
margin-left: auto;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #475569;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background 0.15s;
|
||||
-webkit-appearance: none;
|
||||
font-family: inherit;
|
||||
|
||||
&:hover { background: #f1f5f9; }
|
||||
|
||||
@media (max-width: 600px) {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
||||
&__mobile-menu {
|
||||
border-top: 1px solid #e2e8f0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 8px 12px 12px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
&__mobile-link {
|
||||
padding: 12px 14px;
|
||||
border-radius: 10px;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: #0f172a;
|
||||
text-decoration: none;
|
||||
transition: background 0.15s;
|
||||
|
||||
&:hover { background: #f1f5f9; }
|
||||
}
|
||||
}
|
||||
|
||||
// Wordmark colours
|
||||
.wm-fast {
|
||||
font-weight: 400;
|
||||
font-size: 0.72em;
|
||||
color: #64748b;
|
||||
margin-right: 0.04em;
|
||||
}
|
||||
.wm-check {
|
||||
font-weight: 700;
|
||||
font-size: 1em;
|
||||
color: #1e40af;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
21
src/app/site-header/site-header.ts
Normal file
21
src/app/site-header/site-header.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { TranslatePipe } from '../translate/translate.pipe';
|
||||
import { TranslationService, Lang } from '../translate/translation.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-site-header',
|
||||
imports: [RouterLink, TranslatePipe],
|
||||
templateUrl: './site-header.html',
|
||||
styleUrl: './site-header.scss'
|
||||
})
|
||||
export class SiteHeader {
|
||||
private i18n = inject(TranslationService);
|
||||
|
||||
menuOpen = signal(false);
|
||||
currentLang = this.i18n.currentLang;
|
||||
|
||||
toggleMenu(): void { this.menuOpen.update(v => !v); }
|
||||
closeMenu(): void { this.menuOpen.set(false); }
|
||||
setLang(lang: Lang): void { this.i18n.setLanguage(lang); }
|
||||
}
|
||||
11
src/app/translate/translate.pipe.ts
Normal file
11
src/app/translate/translate.pipe.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Pipe, PipeTransform, inject } from '@angular/core';
|
||||
import { TranslationService } from './translation.service';
|
||||
|
||||
@Pipe({ name: 'translate', pure: false, standalone: true })
|
||||
export class TranslatePipe implements PipeTransform {
|
||||
private svc = inject(TranslationService);
|
||||
|
||||
transform(key: string): string {
|
||||
return this.svc.translate(key);
|
||||
}
|
||||
}
|
||||
36
src/app/translate/translation.service.ts
Normal file
36
src/app/translate/translation.service.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { Injectable, inject, signal } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
export type Lang = 'ru' | 'en' | 'hy';
|
||||
type Translations = Record<string, Record<string, string>>;
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TranslationService {
|
||||
private http = inject(HttpClient);
|
||||
|
||||
currentLang = signal<Lang>('ru');
|
||||
private translations = signal<Translations>({});
|
||||
|
||||
constructor() {
|
||||
this.load('ru');
|
||||
}
|
||||
|
||||
setLanguage(lang: Lang): void {
|
||||
this.currentLang.set(lang);
|
||||
this.load(lang);
|
||||
}
|
||||
|
||||
private load(lang: Lang): void {
|
||||
this.http.get<Translations>(`/i18n/${lang}.json`).subscribe({
|
||||
next: data => this.translations.set(data),
|
||||
});
|
||||
}
|
||||
|
||||
translate(key: string): string {
|
||||
const dot = key.indexOf('.');
|
||||
if (dot === -1) return key;
|
||||
const section = key.slice(0, dot);
|
||||
const k = key.slice(dot + 1);
|
||||
return this.translations()[section]?.[k] ?? key;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Imported via @use './../../../shared' as *;
|
||||
|
||||
.page {
|
||||
min-height: 100dvh;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -29,7 +29,7 @@
|
||||
border-radius: 0;
|
||||
max-width: 100%;
|
||||
box-shadow: none;
|
||||
min-height: 100dvh;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user