Compare commits

...

22 Commits

Author SHA1 Message Date
762e3d8ccc icons 2026-01-03 23:48:13 +01:00
0814913375 time 2026-01-03 16:12:16 +01:00
00bb0b68f0 cimek szétszedve 2026-01-03 16:12:05 +01:00
c3ffa53fcc bugfix kilépés 2026-01-03 16:11:55 +01:00
22edc5d9b7 time 2026-01-03 08:08:40 +01:00
0c80d5bbf9 logo 2026-01-03 08:08:32 +01:00
b24bd3b287 page loading 2026-01-03 08:07:55 +01:00
da254601cf bugfix menü 2026-01-03 08:07:47 +01:00
2f3f41119b ios logo dark mode 2026-01-02 20:25:09 +01:00
0ae2c9ed48 update 2026-01-02 20:23:04 +01:00
ee2a8f1bf8 menu 2026-01-02 20:04:02 +01:00
864e40e25d menu 2026-01-02 20:02:45 +01:00
4162e6ed2a sweep menü 2026-01-02 19:22:14 +01:00
40f4da2386 update app menu 2026-01-02 19:19:19 +01:00
724550745a update 2026-01-02 10:29:43 +01:00
c22430cdb9 update 2025-12-29 18:24:59 +01:00
0f8a4e5208 ios gitignore 2025-12-26 11:49:59 +01:00
5629a480f7 update 2025-12-26 11:46:24 +01:00
76d6e30878 test 2025-12-23 19:51:09 +01:00
ec735c7a4e update 2025-01-02 20:56:21 +01:00
2658719822 update 2025-01-01 23:06:17 +01:00
98b1c11be6 update 2025-01-01 11:15:54 +01:00
79 changed files with 11831 additions and 2374 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Prevents merge conflicts in Ottotime files
.ottotime merge=union

3
.gitignore vendored
View File

@ -22,3 +22,6 @@ logs
.env
.env.*
!.env.example
sw.*
android
ios

92
.ottotime Normal file
View File

@ -0,0 +1,92 @@
# OTTOTIME
# Do not edit manually. Check into git.
1757442553- 12:05
1757443689- 5:33
1757444838- 1:26
1757445608- 4:32
1757926452- 2:43
1757941922- 0:43
1757942775- 0:26
1757943447- 0:04
1757945341- 1:26
1757946951- 0:09
1757947366- 5:35
1758053117- 1:30
1758601520-129:25
1758608989- 0:19
1758611434- 0:49
1758626481- 4:59
1758630609- 0:02
1758641507- 0:03
1758641555- 0:00
1758641557- 1:32
1758643629- 10:08
1758643629- 0:00
1761840745- 0:15
1761842655- 0:02
1763454623- 31:05
1763456925-180:34
1763742068- 0:00
1763742070- 3:41
1763742807- 3:20
1763833236- 0:57
1763924629- 0:10
1766311122- 3:39
1766315097- 5:52
1766316095- 4:02
1766345676- 0:40
1766433481- 0:17
1766434090- 25:55
1766435988- 26:44
1766438813- 3:31
1766505127-209:24
1766523797-241:53
1766567819-999:59
1766627818- 5:26
1766745865- 1:03
1766745972- 0:18
1766750094- 3:08
1766750709- 0:01
1767040128- 9:51
1767041161- 0:22
1767041921- 14:15
1767043405- 10:42
1767044635- 3:33
1767045452- 0:00
1767126192- 0:08
1767126849- 30:00
1767131581- 5:29
1767132321-185:10
1767171670-188:07
1767210073- 9:39
1767211444- 0:04
1767211861- 0:00
1767220551- 3:19
1767221303- 0:00
1767260442- 2:58
1767284298- 0:00
1767292714- 3:54
1767307670- 4:05
1767308254- 1:10
1767308644- 4:02
1767309280- 4:02
1767339059- 0:21
1767339386- 2:51
1767340009- 87:57
1767345728- 93:01
1767373107- 6:35
1767376587- 12:56
1767377746- 15:56
1767379098- 37:13
1767381767- 25:05
1767388089- 13:30
1767389489- 0:04
1767389854-280:04
1767423731- 15:01
1767425256- 4:41
1767427391- 51:16
1767432205- 7:35
1767447810- 11:06
1767449176- 0:51
1767451918- 2:19
1767453092- 0:30

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"git.ignoreLimitWarning": true
}

View File

@ -43,3 +43,10 @@ pnpm run preview
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
View Primevue out the [documentation](https://primevue.org/nuxt) for more information.
## ikon és splash képernyő
Az assets/ mappát megtarthatod - ha később módosítani akarod az icon-t vagy splash-t, csak cseréld le az assets/icon.png vagy assets/splash.png fájlt, és futtasd újra:
pnpm capacitor-assets generate --iconBackgroundColor '#262626' --splashBackgroundColor '#262626'
pnpm cap sync

97
app.vue
View File

@ -1,14 +1,103 @@
<template>
<div class="bg-surface-50 dark:bg-surface-950 dark:text-gray-100 min-h-svh">
<div class="bg-surface-50 dark:bg-surface-950 dark:text-gray-100 min-h-svh safe-area-container">
<Toast />
<NuxtPage />
</div>
</template>
<script setup>
import 'primeicons/primeicons.css'
const nuxtApp = useNuxtApp()
async function loadData() {
// Először betöltjük a tokent (natív appnál Preferences-ből)
await loadToken()
const token = getToken()
}
nuxtApp.hooks.hook('app:mounted', async () => {
})
</script>
<style>
html {
font-size: 14px;
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
/* Safe area kezelés natív appokhoz */
.safe-area-container {
padding-top: env(safe-area-inset-top);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
html {
font-size: 18px;
font-family: "Roboto", serif;
}
/* Natívabb érintés - touch highlight kikapcsolása */
* {
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}
/* Jobb görgetési élmény */
html,
body {
overscroll-behavior: none;
}
html:has(.card-loading),
body:has(.card-loading) {
overflow: hidden;
/* Tiltsuk a görgetést */
}
.text-center {
text-align: center;
}
.text-start {
text-align: start;
}
.text-end {
text-align: end;
}
.card-loading {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
left: 0;
top: 0;
width: 100%;
height: 100%;
backdrop-filter: blur(5px);
z-index: 1;
}
.p-inputotp-input.p-inputtext-sm {
width: 2rem;
}
.p-message {
outline: none;
border-left: 4px;
border-style: solid;
}
.p-disabled,
.p-component:disabled {
opacity: 0.2;
}
pre {
font-size: 13px;
}
</style>

BIN
assets/icon-background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
assets/icon-foreground.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
assets/icon-only.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
assets/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
assets/splash-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

149
assets/splash.svg Normal file
View File

@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="2732"
height="2732"
viewBox="0 0 722.84166 722.84166"
version="1.1"
id="svg257"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="splash.svg"
inkscape:export-filename="Munka/berauto/assets/splash-dark.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
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="namedview259"
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="false"
inkscape:zoom="0.80424311"
inkscape:cx="1213.5634"
inkscape:cy="1368.989"
inkscape:window-width="1920"
inkscape:window-height="1003"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs254" />
<g
inkscape:label="Réteg 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="display:inline;fill:#f9f9f9;stroke-width:6.36842"
id="rect544"
width="722.84167"
height="722.84167"
x="7.1207683e-06"
y="7.1207683e-06"
sodipodi:insensitive="true" />
<path
class="cls-1"
d="m 326.93945,338.10008 c 21.87772,1.70753 43.75544,2.05438 65.4375,4.79355 l -0.0622,0.88932 c -9.03569,-0.48022 -18.06246,-1.04051 -27.09815,-1.40514 -12.87759,-0.52473 -25.79078,-0.82707 -38.63285,-1.37849 -3.55735,-0.16 -8.00405,0.48025 -10.81435,4.07319 h -3.9131 a 21.264075,21.264075 0 0 1 2.66802,-3.29947 c -12.85981,0.5603 -28.52996,2.66803 -36.24053,11.30351 l 14.07824,-0.24906 c 6.98131,-4.90025 16.08812,-4.98028 21.97554,3.41506 l -3.48619,-0.0535 c -5.33603,-5.73622 -11.01003,-5.23822 -15.39445,-2.17888 -2.18779,1.52965 -3.0949,2.17888 -3.0949,2.17888 H 271.4626 c 0.14218,-3.47731 1.94766,-5.80738 4.23326,-7.61276 7.04356,-5.56725 15.40332,-7.8795 24.01213,-9.18684 6.46548,-0.96939 13.02878,-1.27177 19.56542,-1.94766 a 9.0001013,9.0001013 0 0 0 3.31725,-0.88933 86.434772,86.434772 0 0 1 40.3048,-10.76099 c 17.93796,-0.42689 35.21778,3.05042 52.07076,8.65326 9.32915,3.0949 19.44092,7.86174 28.57443,11.56139 0.84486,0.33795 -0.25781,1.07608 -0.88933,0.80039 a 274.28077,274.28077 0 0 0 -53.79608,-16.41715 c -11.56139,-2.21448 -18.6761,-2.35676 -30.44205,-1.92988 -9.91611,0.32907 -23.01605,4.23326 -31.47367,9.64041 z"
id="path8"
style="fill:#c7081c;stroke-width:0.889338" />
<path
class="cls-2"
d="m 275.01987,363.95314 h 3.30834 q 3.2194,0 6.67005,-0.0535 l 0.0978,0.10655 -0.81817,4.44667 -0.72039,0.0269 -0.84486,-3.2194 h -5.12259 v 7.03465 h 0.71148 2.48123 a 0.46245581,0.46245581 0 0 0 0.44467,-0.36463 l 0.48026,-1.77865 h 0.88932 c 0,1.28064 0,2.24113 0,2.87254 0,0.63142 0,1.56525 0,2.82812 l -0.88932,0.0712 -0.46245,-1.92985 a 0.44466904,0.44466904 0 0 0 -0.4091,-0.37353 h -2.51682 -0.72927 v 4.54451 q 0,1.45853 0,2.88146 h 5.29156 l 1.67197,-3.47731 0.80929,-0.12437 -0.31999,4.95362 -0.0978,0.0891 q -3.29056,0 -6.41211,0 h -3.51291 c -1.13833,0 -2.31225,0 -3.55734,0 v -0.66701 l 1.77869,-0.48913 a 0.44466904,0.44466904 0 0 0 0.35572,-0.40019 c 0,-0.35576 0,-0.74705 0,-1.18284 0,-0.43579 0,-0.88932 0,-1.44962 v -10.57424 c 0,-0.44467 0,-0.84486 0,-1.20949 0,-0.36463 0,-0.69367 0,-0.98717 a 0.4268823,0.4268823 0 0 0 -0.35572,-0.43576 l -1.77869,-0.51583 v -0.67588 q 1.85872,0.0535 3.55734,0.0535 z"
id="path10"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-2"
d="m 290.81453,363.8998 c 1.22728,0 2.58796,0.0535 4.07315,0.0535 1.48521,0 2.89927,0 4.08207,-0.0535 l 0.0622,0.67589 -1.7164,0.48913 a 0.40909553,0.40909553 0 0 0 -0.34685,0.39132 c 0,0.31999 0,0.65811 0,1.03161 0,0.37354 0,0.75595 0,1.18284 v 7.29255 q 0,3.61963 1.08498,4.99809 a 4.2154627,4.2154627 0 0 0 3.55734,1.37846 4.3933304,4.3933304 0 0 0 3.55738,-1.45849 q 1.20061,-1.4674 1.20061,-4.74909 v -7.46152 c 0,-0.42689 0,-0.81821 0,-1.18284 0,-0.36463 0,-0.71145 0,-1.03161 a 0.40909553,0.40909553 0 0 0 -0.34685,-0.39132 l -1.63641,-0.46244 v -0.70258 c 1.17393,0 2.1967,0.0535 3.05046,0.0535 0.85377,0 1.77866,0 2.98819,-0.0535 l 0.0622,0.67589 -1.7787,0.51582 a 0.4268823,0.4268823 0 0 0 -0.32906,0.43575 c 0,0.29345 0,0.63145 0,0.98717 0,0.35573 0,0.76483 0,1.20949 v 6.7234 q 0,4.54451 -1.87651,6.52778 a 7.1147047,7.1147047 0 0 1 -5.44274,1.98322 c -2.71248,0 -4.70459,-0.63145 -5.99414,-1.88541 -1.28952,-1.25397 -1.92985,-3.27278 -1.92985,-6.04751 v -7.30148 c 0,-0.44466 0,-0.84485 0,-1.20949 0,-0.36462 0,-0.69366 0,-0.98717 a 0.4268823,0.4268823 0 0 0 -0.32033,-0.43575 l -1.77868,-0.51582 z"
id="path12"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-2"
d="m 321.69236,378.26261 c 0,0.5247 0,1.00496 0,1.42293 0,0.41797 0,0.80039 0,1.13837 0,0.33794 0.11563,0.46244 0.30217,0.51578 l 1.40519,0.48026 0.0444,0.65811 c -0.9783,0 -2.1967,0 -3.64632,0 -1.44961,0 -2.91701,0 -4.1265,0 l -0.0621,-0.65811 1.77864,-0.48913 a 0.43577567,0.43577567 0 0 0 0.32034,-0.4002 c 0,-0.35575 0,-0.74704 0,-1.18283 0,-0.43579 0,-0.88933 0,-1.44962 v -10.57425 c 0,-0.44466 0,-0.84485 0,-1.20949 0,-0.36462 0,-0.69366 0,-0.98717 a 0.4268823,0.4268823 0 0 0 -0.31126,-0.43575 l -1.77868,-0.51582 v -0.67589 c 1.23618,0 2.49904,0.0535 3.79747,0.0535 h 1.01386 l 1.48518,-0.0444 h 1.33403 0.83598 a 9.2935833,9.2935833 0 0 1 5.10478,1.13837 3.753007,3.753007 0 0 1 1.69865,3.32611 4.7312787,4.7312787 0 0 1 -1.04051,3.18384 6.6344622,6.6344622 0 0 1 -3.05047,1.85872 c 0.73818,1.09385 1.31624,1.97431 1.71644,2.66801 0.4002,0.69367 0.75595,1.28953 1.20062,1.91207 0.44466,0.62254 0.77373,1.23618 1.10277,1.77868 a 7.7372417,7.7372417 0 0 0 0.93379,1.15615 4.8113191,4.8113191 0 0 0 0.46248,0.34682 3.6996467,3.6996467 0 0 0 0.45354,0.24907 4.2421428,4.2421428 0 0 0 0.50695,0.17781 l 0.60472,0.14219 0.0535,0.66697 a 21.059526,21.059526 0 0 1 -2.9704,0.18689 6.794543,6.794543 0 0 1 -1.84981,-0.16907 3.0593231,3.0593231 0 0 1 -0.94271,-0.48914 5.2737749,5.2737749 0 0 1 -1.11167,-1.24508 c -0.33795,-0.51582 -0.70258,-1.0939 -1.08499,-1.77869 -0.38242,-0.6848 -0.76483,-1.32512 -1.16506,-2.05438 -0.40019,-0.72923 -0.82707,-1.43181 -1.26283,-2.14329 l -0.32907,-0.49804 a 1.2895402,1.2895402 0 0 0 -0.24907,-0.30251 0.88933813,0.88933813 0 0 0 -0.26688,-0.14219 1.1561395,1.1561395 0 0 0 -0.34685,-0.0621 h -0.56026 z m 0,-5.57617 c 0.47135,0 0.88933,0 1.27174,0 a 3.5573524,3.5573524 0 0 0 2.74804,-0.89823 4.2777163,4.2777163 0 0 0 0.88937,-2.9526 4.0198084,4.0198084 0 0 0 -0.88937,-2.837 3.4328453,3.4328453 0 0 0 -2.61463,-0.88932 h -0.64924 l -0.79151,0.08 z"
id="path14"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-2"
d="m 357.47041,372.76648 a 10.120668,10.120668 0 0 1 -2.66801,7.36372 q -2.66801,2.78364 -7.51491,2.78364 -4.60676,0 -7.11468,-2.5702 a 9.5425983,9.5425983 0 0 1 -2.51683,-6.9724 9.6848925,9.6848925 0 0 1 2.66802,-7.24812 c 1.77865,-1.77866 4.31329,-2.66802 7.506,-2.66802 3.19271,0 5.44275,0.82711 7.11472,2.49017 a 9.1423955,9.1423955 0 0 1 2.52569,6.82121 z m -15.40331,0.15999 c 0,2.81921 0.47135,4.98028 1.43182,6.47437 a 4.6423449,4.6423449 0 0 0 4.1888,2.25004 4.4466904,4.4466904 0 0 0 4.02869,-2.0366 q 1.30734,-2.04547 1.30734,-6.41212 a 11.970491,11.970491 0 0 0 -1.37849,-6.30541 4.6690252,4.6690252 0 0 0 -4.25992,-2.20557 4.4466904,4.4466904 0 0 0 -4.05539,2.0455 c -0.84488,1.37847 -1.26285,3.43285 -1.26285,6.18979 z"
id="path16"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-2"
d="m 388.1526,368.89785 -0.72927,0.1247 -1.00495,-3.80637 a 7.6572012,7.6572012 0 0 0 -2.25892,-0.32907 5.2648816,5.2648816 0 0 0 -4.52672,2.19666 9.4892379,9.4892379 0 0 0 -1.60081,5.73625 9.0445691,9.0445691 0 0 0 1.92988,6.0297 6.438808,6.438808 0 0 0 5.2293,2.25005 11.330167,11.330167 0 0 0 3.93085,-0.75596 l 0.17781,0.75596 a 10.41415,10.41415 0 0 1 -5.98523,1.77865 9.5603854,9.5603854 0 0 1 -6.99021,-2.61464 9.1512891,9.1512891 0 0 1 -2.66802,-6.86568 9.1868624,9.1868624 0 0 1 2.92593,-7.18587 10.947752,10.947752 0 0 1 7.6305,-2.66802 22.233452,22.233452 0 0 1 4.76687,0.54251 l 0.08,0.13345 z"
id="path18"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-2"
d="m 398.73572,376.54617 -0.94271,2.48126 c -0.18688,0.48023 -0.32907,0.88933 -0.42688,1.16502 a 2.2500255,2.2500255 0 0 0 -0.16,0.68479 0.47134919,0.47134919 0 0 0 0.12437,0.34685 0.80929768,0.80929768 0 0 0 0.3735,0.17782 l 1.26287,0.3735 v 0.6848 c -1.28065,0 -2.32117,0 -3.12159,0 -0.80037,0 -1.77865,0 -2.87254,0 l -0.0269,-0.64032 1.42297,-0.42689 a 1.2984336,1.2984336 0 0 0 0.71145,-0.46244 5.3360287,5.3360287 0 0 0 0.52472,-1.02274 l 6.58999,-16.08816 1.43184,-0.21343 5.70953,16.08815 a 4.31329,4.31329 0 0 0 0.59585,1.25396 1.609702,1.609702 0 0 0 0.77373,0.47135 l 1.29844,0.38241 0.0444,0.65811 c -1.19171,0 -2.39233,0 -3.60181,0 -1.6008,0 -3.15714,0 -4.66901,0 l -0.0712,-0.65811 1.30734,-0.38241 a 0.94269839,0.94269839 0 0 0 0.39131,-0.19563 0.49802932,0.49802932 0 0 0 0.11564,-0.36463 2.5612937,2.5612937 0 0 0 -0.13344,-0.6937 c -0.0891,-0.2847 -0.21345,-0.65811 -0.38242,-1.12946 l -0.88933,-2.49013 z m 2.85476,-7.59494 c -0.15999,0.46244 -0.32907,0.88933 -0.51582,1.43184 l -1.77865,4.79352 h 4.44667 l -1.62747,-4.78464 c -0.23126,-0.49801 -0.38241,-0.97828 -0.52473,-1.44072 z"
id="path20"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-2"
d="m 422.65003,378.26261 v 1.42293 c 0,0.41797 0,0.80039 0,1.13837 0,0.33794 0.10689,0.46244 0.30252,0.51578 l 1.37849,0.45357 v 0.65811 c -0.97826,0 -2.19666,0 -3.6374,0 -1.44071,0 -2.92593,0 -4.13542,0 l -0.0621,-0.65811 1.77869,-0.48913 a 0.44466904,0.44466904 0 0 0 0.36463,-0.4091 c 0,-0.35573 0,-0.74704 0,-1.1828 0,-0.43579 0,-0.88937 0,-1.44962 v -10.53869 c 0,-0.44466 0,-0.84485 0,-1.20949 0,-0.36462 0,-0.69366 0,-0.98717 a 0.4268823,0.4268823 0 0 0 -0.31999,-0.43575 l -1.77869,-0.51582 v -0.67589 c 1.23618,0 2.49904,0.0535 3.79747,0.0535 h 1.02273 l 1.47631,-0.0444 h 1.33399 0.83599 a 9.2757962,9.2757962 0 0 1 5.10481,1.13837 3.7352201,3.7352201 0 0 1 1.69862,3.32611 4.7757457,4.7757457 0 0 1 -1.03161,3.18384 6.6878225,6.6878225 0 0 1 -3.05043,1.85872 c 0.73813,1.09385 1.3073,1.97431 1.70753,2.66801 0.40019,0.69367 0.79151,1.28953 1.21839,1.91207 0.42689,0.62254 0.7737,1.23618 1.11168,1.77868 a 7.7372417,7.7372417 0 0 0 0.90711,1.15615 4.7490656,4.7490656 0 0 0 0.45357,0.34682 3.6996467,3.6996467 0 0 0 0.45357,0.24907 3.895301,3.895301 0 0 0 0.51579,0.17781 l 0.59585,0.14219 0.0535,0.66697 a 20.926126,20.926126 0 0 1 -2.96147,0.18689 6.7500763,6.7500763 0 0 1 -1.84985,-0.16907 3.0593231,3.0593231 0 0 1 -0.94268,-0.48914 5.113694,5.113694 0 0 1 -1.12058,-1.24508 c -0.33794,-0.51582 -0.70257,-1.0939 -1.07611,-1.77869 -0.37351,-0.6848 -0.7737,-1.32512 -1.17393,-2.05438 -0.40019,-0.72923 -0.81817,-1.43181 -1.26283,-2.14329 l -0.32033,-0.49804 a 1.2984336,1.2984336 0 0 0 -0.25781,-0.30251 0.81819105,0.81819105 0 0 0 -0.25781,-0.14219 1.2806469,1.2806469 0 0 0 -0.35576,-0.0621 h -0.51579 z m 0,-5.57617 c 0.46244,0 0.88933,0 1.26284,0 a 3.5573524,3.5573524 0 0 0 2.75694,-0.95161 4.2777163,4.2777163 0 0 0 0.88937,-2.95257 4.0198084,4.0198084 0 0 0 -0.83599,-2.83699 3.4328453,3.4328453 0 0 0 -2.61467,-0.88936 h -0.6581 l -0.78261,0.08 z"
id="path22"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-2"
d="m 448.2185,365.15376 a 4.9358265,4.9358265 0 0 0 -1.83203,-0.32907 3.5573524,3.5573524 0 0 0 -2.37454,0.8182 2.6680144,2.6680144 0 0 0 -0.97826,2.11663 2.5968673,2.5968673 0 0 0 0.32032,1.33399 3.5573524,3.5573524 0 0 0 0.84487,0.99608 6.5811018,6.5811018 0 0 0 1.20948,0.78261 c 0.45357,0.23126 0.88936,0.45357 1.41406,0.68479 0.52472,0.23125 1.0761,0.54248 1.62749,0.84486 a 7.1147047,7.1147047 0 0 1 1.4674,1.08499 4.8024259,4.8024259 0 0 1 1.04942,1.50299 4.9091464,4.9091464 0 0 1 0.4091,2.11663 4.9980802,4.9980802 0 0 1 -2.04547,4.21545 8.5732188,8.5732188 0 0 1 -5.33602,1.53856 15.118747,15.118747 0 0 1 -4.7224,-0.75592 l -0.08,-0.11563 0.69367,-4.76686 0.82708,-0.13344 0.98717,4.05538 a 5.1492677,5.1492677 0 0 0 2.11663,0.43575 4.1087421,4.1087421 0 0 0 2.71249,-0.88933 2.8192018,2.8192018 0 0 0 1.02273,-2.25003 2.7391614,2.7391614 0 0 0 -0.32033,-1.36959 3.5039921,3.5039921 0 0 0 -0.88933,-1.00492 6.8479033,6.8479033 0 0 0 -1.23618,-0.79152 l -1.42295,-0.68479 c -0.54248,-0.26689 -1.08499,-0.54252 -1.6186,-0.83599 a 5.9140983,5.9140983 0 0 1 -1.44071,-1.05833 4.6779184,4.6779184 0 0 1 -1.03164,-1.48517 4.9891869,4.9891869 0 0 1 -0.4002,-2.09885 4.8024259,4.8024259 0 0 1 1.92985,-4.01979 7.9240026,7.9240026 0 0 1 5.01587,-1.50299 19.014048,19.014048 0 0 1 4.44669,0.61363 l 0.08,0.11562 -0.8093,4.25992 -0.72926,0.12437 z"
id="path24"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-3"
d="m 320.20714,394.7687 v 0.71149 c 0,0.21344 0,0.40019 0,0.57806 a 0.25790806,0.25790806 0 0 0 0.16,0.25782 l 0.6848,0.22218 v 0.32907 h -1.7787 -2.07216 v -0.32907 l 0.88933,-0.24 a 0.22233452,0.22233452 0 0 0 0.17781,-0.21344 c 0,-0.16907 0,-0.37353 0,-0.58698 v -6.5633 c 0,-0.18688 0,-0.34685 0,-0.49804 a 0.21344115,0.21344115 0 0 0 -0.15126,-0.22219 l -0.88933,-0.2578 v -0.33794 q 0.88933,0 1.89429,0 h 0.51582 0.73814 0.66701 0.41797 a 4.6156649,4.6156649 0 0 1 2.55242,0.56919 1.8765035,1.8765035 0 0 1 0.80931,1.63638 2.3478526,2.3478526 0 0 1 -0.51583,1.59189 3.2105105,3.2105105 0 0 1 -1.52965,0.93384 c 0.37351,0.54248 0.65811,0.98714 0.88933,1.32511 0.23125,0.33795 0.40019,0.67589 0.60476,1.00493 0.20436,0.32906 0.38241,0.62254 0.55139,0.88936 a 4.2421428,4.2421428 0 0 0 0.46244,0.59586 l 0.23126,0.16907 a 0.83597782,0.83597782 0 0 0 0.23125,0.12436 l 0.24907,0.0978 0.30252,0.0622 v 0.33795 a 10.343002,10.343002 0 0 1 -1.47631,0.0978 3.5573524,3.5573524 0 0 1 -0.88933,-0.0891 1.6274888,1.6274888 0 0 1 -0.46248,-0.23999 2.7302679,2.7302679 0 0 1 -0.56025,-0.62254 c -0.16908,-0.25781 -0.35576,-0.55139 -0.54251,-0.88937 l -0.58699,-1.02273 c -0.19563,-0.36463 -0.40906,-0.72035 -0.63141,-1.07608 l -0.16,-0.24907 a 0.80040431,0.80040431 0 0 0 -0.1247,-0.15126 l -0.13344,-0.0712 a 0.49802932,0.49802932 0 0 0 -0.17781,0 h -0.27563 z m 0,-2.78361 c 0.23126,0 0.44467,0 0.63145,0 a 1.7786762,1.7786762 0 0 0 1.37847,-0.47135 2.1077314,2.1077314 0 0 0 0.43578,-1.4763 2.0632644,2.0632644 0 0 0 -0.418,-1.42294 1.7786762,1.7786762 0 0 0 -1.30734,-0.44469 h -0.32907 -0.39133 z"
id="path26"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-3"
d="m 329.563,387.60955 h 1.67197 3.335 l 0.0444,0.0535 -0.4091,2.16111 -0.35573,0.0535 -0.42688,-1.60967 h -2.55239 v 3.55734 h 1.5919 a 0.23122792,0.23122792 0 0 0 0.22219,-0.17781 l 0.23999,-0.88937 h 0.43579 c 0,0.64033 0,1.11168 0,1.43184 0,0.32034 0,0.78261 0,1.41406 h -0.43579 l -0.24907,-0.88932 a 0.22233452,0.22233452 0 0 0 -0.20437,-0.22219 h -1.6008 v 2.26782 c 0,0.48914 0,0.96936 0,1.44072 h 2.66801 l 0.82708,-1.77866 0.4091,-0.0621 -0.16907,2.46348 v 0 h -3.21053 -1.77869 -1.77866 v -0.32907 l 0.88933,-0.24 a 0.24012129,0.24012129 0 0 0 0.17781,-0.21343 c 0,-0.16908 0,-0.37354 0,-0.58699 v -6.51883 c 0,-0.18688 0,-0.34685 0,-0.49804 a 0.23122792,0.23122792 0 0 0 -0.15999,-0.22218 l -0.88933,-0.25781 v -0.33794 z"
id="path28"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-3"
d="m 338.83879,396.04936 a 0.22233452,0.22233452 0 0 0 0.16907,0.23125 l 0.88936,0.23126 v 0.33794 h -1.46743 -1.49409 v -0.32907 l 0.88936,-0.24 a 0.23122792,0.23122792 0 0 0 0.18689,-0.21344 c 0,-0.35573 0,-0.79148 0,-1.31621 v -5.256 c 0,-0.43576 0,-0.80039 0,-1.09386 a 0.23122792,0.23122792 0 0 0 -0.16,-0.22218 l -0.88936,-0.25782 v -0.33794 h 1.42296 q 0.64033,0 1.22728,0 l 4.40222,5.51391 0.54248,0.70258 c 0,-0.30251 0,-0.59585 0,-0.88936 v -3.44172 c 0,-0.42688 0,-0.79151 0,-1.1028 a 0.20454778,0.20454778 0 0 0 -0.16907,-0.19563 l -0.88933,-0.23125 v -0.35573 h 1.48518 1.47631 v 0.33794 l -0.88933,0.25782 a 0.23122792,0.23122792 0 0 0 -0.16,0.22218 c 0,0.29344 0,0.6581 0,1.09386 v 7.35485 l -0.84485,0.0891 -5.2204,-6.52778 -0.53361,-0.71145 c 0,0.32907 0,0.63142 0,0.88933 v 4.1888 c 0.0168,0.51581 0.0168,0.9427 0.0269,1.27173 z"
id="path30"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-3"
d="m 352.03657,396.84977 h -2.22335 v -0.32906 l 1.05834,-0.29345 a 0.22233452,0.22233452 0 0 0 0.16907,-0.20437 c 0,-0.33797 0,-0.76485 0,-1.28064 v -6.44771 h -1.92097 l -0.60476,1.77865 -0.37354,0.0622 -0.19563,-2.49904 v -0.0535 h 3.11268 1.84981 3.13937 v 0.0535 l -0.43579,2.42792 -0.37351,0.0535 -0.42688,-1.77866 h -1.80534 v 6.46549 c 0,0.51579 0,0.94268 0,1.28065 a 0.23122792,0.23122792 0 0 0 0.18689,0.20437 l 1.03161,0.29344 v 0.32906 z"
id="path32"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-3"
d="m 363.66021,393.91494 -0.46244,1.24509 c -0.0978,0.23998 -0.16908,0.43578 -0.22219,0.58694 a 1.2717535,1.2717535 0 0 0 -0.0712,0.33797 0.21344115,0.21344115 0 0 0 0.0621,0.16908 0.37352201,0.37352201 0 0 0 0.17781,0.0978 l 0.64033,0.18688 v 0.33797 h -1.56525 -1.43184 v -0.32907 l 0.71148,-0.21343 a 0.63143005,0.63143005 0 0 0 0.37351,-0.24 3.6818599,3.6818599 0 0 0 0.25781,-0.50691 l 3.29943,-8.00405 0.71149,-0.10689 2.85476,8.04851 a 2.098838,2.098838 0 0 0 0.30251,0.62255 0.7915109,0.7915109 0 0 0 0.38241,0.23999 l 0.64923,0.18689 v 0.32907 h -1.77867 -2.33896 v -0.32907 l 0.64921,-0.18689 a 0.45356244,0.45356244 0 0 0 0.19562,-0.10689 0.24901466,0.24901466 0 0 0 0.0622,-0.17781 1.2539667,1.2539667 0 0 0 -0.0712,-0.34685 l -0.18689,-0.56028 -0.44466,-1.24506 z m 1.43184,-3.79748 c -0.08,0.22252 -0.16,0.46248 -0.25781,0.71149 l -0.88933,2.39232 h 2.21444 l -0.81817,-2.38345 z"
id="path34"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-3"
d="m 383.35904,390.09077 -0.3646,0.0535 -0.50694,-1.89429 a 3.5573524,3.5573524 0 0 0 -1.12945,-0.16907 2.6680144,2.6680144 0 0 0 -2.28561,1.09387 4.7579588,4.7579588 0 0 0 -0.80038,2.87258 4.5623046,4.5623046 0 0 0 0.9427,3.01486 3.2282974,3.2282974 0 0 0 2.62355,1.12946 5.6117235,5.6117235 0 0 0 1.96543,-0.38241 l 0.08,0.38241 a 5.2115213,5.2115213 0 0 1 -2.98817,0.88932 4.7757457,4.7757457 0 0 1 -3.49509,-1.30733 4.5711978,4.5711978 0 0 1 -1.33402,-3.43284 4.6156649,4.6156649 0 0 1 1.45852,-3.55734 5.4961096,5.4961096 0 0 1 3.82417,-1.32512 10.529763,10.529763 0 0 1 2.3745,0.27562 v 0.0622 z"
id="path36"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-3"
d="m 387.96585,393.91494 -0.47135,1.24509 -0.21345,0.58694 a 1.049419,1.049419 0 0 0 -0.08,0.33797 0.24012129,0.24012129 0 0 0 0.0622,0.16908 0.46245581,0.46245581 0 0 0 0.18689,0.0978 l 0.63141,0.18688 v 0.33797 h -1.56521 -1.43184 v -0.32907 l 0.71145,-0.21343 a 0.63143005,0.63143005 0 0 0 0.39132,-0.28471 2.8192018,2.8192018 0 0 0 0.26689,-0.50691 l 3.29946,-8.00405 0.71148,-0.10655 2.83699,8.05742 a 2.1344115,2.1344115 0 0 0 0.29344,0.62252 0.88933813,0.88933813 0 0 0 0.39132,0.23999 l 0.6492,0.18688 v 0.32907 h -1.77869 -2.33895 v -0.32907 l 0.65811,-0.18688 a 0.45356244,0.45356244 0 0 0 0.19563,-0.10689 0.24901466,0.24901466 0 0 0 0.0535,-0.17781 1.1917131,1.1917131 0 0 0 -0.0621,-0.34682 c 0,-0.14218 -0.10656,-0.32907 -0.19563,-0.56029 l -0.4358,-1.24508 z m 1.43184,-3.79748 -0.25782,0.71149 -0.88936,2.39232 h 2.20557 l -0.80929,-2.38345 c -0.10656,-0.25781 -0.17781,-0.49801 -0.24908,-0.72036 z"
id="path38"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-3"
d="m 399.22485,394.7687 c 0,0.26689 0,0.50695 0,0.71149 0,0.20469 0,0.40019 0,0.57806 a 0.24012129,0.24012129 0 0 0 0.15126,0.25782 l 0.68479,0.22218 v 0.32907 h -1.82316 -2.06325 v -0.32907 l 0.88933,-0.24 a 0.24012129,0.24012129 0 0 0 0.17781,-0.21344 c 0,-0.16907 0,-0.37353 0,-0.58698 v -6.5633 c 0,-0.18688 0,-0.34685 0,-0.49804 a 0.23122792,0.23122792 0 0 0 -0.16001,-0.22219 l -0.88935,-0.2578 v -0.33794 c 0.61363,0 1.25395,0 1.90319,0 h 0.54251 0.73814 0.66701 0.3735 a 4.597878,4.597878 0 0 1 2.55243,0.56919 1.8587167,1.8587167 0 0 1 0.88932,1.65416 2.356746,2.356746 0 0 1 -0.52469,1.59193 3.2194039,3.2194039 0 0 1 -1.52078,0.9338 c 0.36463,0.54248 0.6581,0.98717 0.88933,1.32512 0.23125,0.33794 0.40019,0.67588 0.60476,1.00495 l 0.55138,0.88933 a 3.6551797,3.6551797 0 0 0 0.47135,0.59586 c 0.08,0.0621 0.15126,0.12436 0.22219,0.16906 a 0.9782719,0.9782719 0 0 0 0.23126,0.12438 l 0.2578,0.0978 0.30218,0.0622 v 0.33795 a 10.57423,10.57423 0 0 1 -1.48518,0.0978 3.5573524,3.5573524 0 0 1 -0.88932,-0.0887 1.5652351,1.5652351 0 0 1 -0.47136,-0.24 2.7302679,2.7302679 0 0 1 -0.56029,-0.62254 c -0.16907,-0.25781 -0.34685,-0.55139 -0.54251,-0.88933 -0.19563,-0.33798 -0.38242,-0.66701 -0.57804,-1.02274 -0.19563,-0.35576 -0.41801,-0.72039 -0.63145,-1.07611 l -0.16907,-0.24907 a 0.43577567,0.43577567 0 0 0 -0.12437,-0.15126 l -0.13345,-0.0712 a 0.48024259,0.48024259 0 0 0 -0.16907,0 h -0.2847 z m 0,-2.78361 c 0.24,0 0.44466,0 0.64032,0 a 1.7786762,1.7786762 0 0 0 1.37849,-0.47135 2.1521982,2.1521982 0 0 0 0.43577,-1.4763 2.0187975,2.0187975 0 0 0 -0.42689,-1.42294 1.7164225,1.7164225 0 0 0 -1.30733,-0.44469 h -0.32 -0.40019 z"
id="path40"
style="fill:#333333;stroke-width:0.889338" />
<path
class="cls-4"
d="m 292.17523,390.42875 h 19.44093 v 2.06325 h -39.94019 c 0,0 14.01596,-2.06325 20.49926,-2.06325 z"
id="path42"
style="fill:#808080;stroke-width:0.889338" />
<path
class="cls-4"
d="m 430.65408,390.42875 h -19.43206 v 2.06325 h 39.94019 c 0,0 -14.05156,-2.06325 -20.50813,-2.06325 z"
id="path44"
style="fill:#808080;stroke-width:0.889338" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -1,15 +1,15 @@
:root {
--p-primary-50: #ecfdf5;
--p-primary-100: #d1fae5;
--p-primary-200: #a7f3d0;
--p-primary-300: #6ee7b7;
--p-primary-400: #34d399;
--p-primary-500: #10b981;
--p-primary-600: #059669;
--p-primary-700: #047857;
--p-primary-800: #065f46;
--p-primary-900: #064e3b;
--p-primary-950: #022c22;
--p-primary-50: #fcf3f4;
--p-primary-100: #f2c4c8;
--p-primary-200: #e7959d;
--p-primary-300: #dd6672;
--p-primary-400: #d23846;
--p-primary-500: #c8091b;
--p-primary-600: #aa0817;
--p-primary-700: #8c0613;
--p-primary-800: #6e050f;
--p-primary-900: #50040b;
--p-primary-950: #320207;
--p-surface-0: #ffffff;
--p-surface-50: #fafafa;
--p-surface-100: #f4f4f5;

756
assets/styles/fonts.css Normal file
View File

@ -0,0 +1,756 @@
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOiCnqEu92Fr1Mu51QrEz0dL_nz.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOiCnqEu92Fr1Mu51QrEzQdL_nz.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOiCnqEu92Fr1Mu51QrEzwdL_nz.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOiCnqEu92Fr1Mu51QrEzMdL_nz.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOiCnqEu92Fr1Mu51QrEz8dL_nz.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOiCnqEu92Fr1Mu51QrEz4dL_nz.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOiCnqEu92Fr1Mu51QrEzAdLw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TjASc3CsTKlA.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TjASc-CsTKlA.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TjASc2CsTKlA.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TjASc5CsTKlA.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TjASc1CsTKlA.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TjASc0CsTKlA.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TjASc6CsQ.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1Mu51xFIzIFKw.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1Mu51xMIzIFKw.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1Mu51xEIzIFKw.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1Mu51xLIzIFKw.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1Mu51xHIzIFKw.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1Mu51xGIzIFKw.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1Mu51xIIzI.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51S7ACc3CsTKlA.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51S7ACc-CsTKlA.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51S7ACc2CsTKlA.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51S7ACc5CsTKlA.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51S7ACc1CsTKlA.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51S7ACc0CsTKlA.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51S7ACc6CsQ.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TzBic3CsTKlA.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TzBic-CsTKlA.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TzBic2CsTKlA.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TzBic5CsTKlA.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TzBic1CsTKlA.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TzBic0CsTKlA.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TzBic6CsQ.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TLBCc3CsTKlA.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TLBCc-CsTKlA.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TLBCc2CsTKlA.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TLBCc5CsTKlA.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TLBCc1CsTKlA.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TLBCc0CsTKlA.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOjCnqEu92Fr1Mu51TLBCc6CsQ.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1MmgVxFIzIFKw.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1MmgVxMIzIFKw.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1MmgVxEIzIFKw.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1MmgVxLIzIFKw.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1MmgVxHIzIFKw.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1MmgVxGIzIFKw.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 100;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOkCnqEu92Fr1MmgVxIIzI.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 300;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmSU5fBBc4.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu72xKOzY.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu5mxKOzY.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu7mxKOzY.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu4WxKOzY.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu7WxKOzY.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu7GxKOzY.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOmCnqEu92Fr1Mu4mxK.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmEU9fCRc4EsA.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmEU9fABc4EsA.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmEU9fCBc4EsA.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmEU9fBxc4EsA.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmEU9fCxc4EsA.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmEU9fChc4EsA.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmEU9fBBc4.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmWUlfBBc4.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmYUtfCRc4EsA.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmYUtfABc4EsA.woff2) format('woff2');
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* greek-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmYUtfCBc4EsA.woff2) format('woff2');
unicode-range: U+1F00-1FFF;
}
/* greek */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmYUtfBxc4EsA.woff2) format('woff2');
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
}
/* vietnamese */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmYUtfCxc4EsA.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
}
/* latin-ext */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmYUtfChc4EsA.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url(https://fonts.gstatic.com/s/roboto/v32/KFOlCnqEu92Fr1MmYUtfBBc4.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

View File

@ -1,5 +1,5 @@
.p-toast {
@apply w-96 rounded-md whitespace-pre-line break-words
@apply w-full max-w-96 rounded-md whitespace-pre-line break-words
}
.p-toast-message {

BIN
assets/styles/splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -1,4 +1,4 @@
@import "tailwindcss/base";
@import "tailwindcss/components";
@import "./primevue/tailwind.css";
@import "tailwindcss/utilities";
@import "tailwindcss/utilities";

24
capacitor.config.ts Normal file
View File

@ -0,0 +1,24 @@
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'app.olcsoberauto.hu',
appName: 'Eurocars Rent A Car',
webDir: '.output/public',
plugins: {
SplashScreen: {
launchShowDuration: 2000,
launchAutoHide: true,
backgroundColor: '#262626',
androidScaleType: 'CENTER_CROP',
showSpinner: false
},
StatusBar: {
overlaysWebView: false
}
},
android: {
backgroundColor: '#262626'
}
};
export default config;

13
components/Alert.vue Normal file
View File

@ -0,0 +1,13 @@
<template>
<div>
</div>
</template>
<script lang="ts" setup>
</script>
<style>
</style>

256
components/AppMenu.vue Normal file
View File

@ -0,0 +1,256 @@
<template>
<div class="min-h-12 w-full z-10 top-0 fixed bg-neutral-800 flex justify-between items-center pe-2">
<div v-if="isHome" @click="$router.push({ path: '/' })"
class="bg-neutral-800 h-12 flex items-center shadow">
<Logo dark class="h-8 mx-3" />
</div>
<div v-else class="text-sm opacity-80 h-12 flex items-center">
<div class="ms-3 flex gap-2 items-center text-white" @click="$router.back()">
<i class="pi pi-arrow-left text-red-500"></i> vissza
</div>
</div>
<div v-if="props.menu">
<!-- Backdrop overlay -->
<div
class="fixed inset-0 bg-black z-40"
:class="backdropClass"
:style="{ opacity: backdropOpacity }"
@click="closeMenu"
></div>
<!-- Swipeable Drawer -->
<div
ref="drawerRef"
class="fixed top-0 right-0 h-full w-72 bg-surface-0 dark:bg-surface-900 z-50 shadow-xl will-change-transform"
:class="drawerClass"
:style="drawerStyle"
>
<div class="p-4">
<div class="flex flex-col mb-4">
<div class="font-medium">{{ auth.user?.nev }}</div>
<div class="text-xs opacity-70">{{ auth.user?.email }}</div>
</div>
<div class="flex flex-col space-y-3 text-sm">
<NuxtLink to="/profile" @click="closeMenu">Adataim</NuxtLink>
<Divider />
<NuxtLink
v-for="p in config?.config.menu"
:to="'/page/' + p.id"
:key="p.id"
@click="isOpen = false"
>{{ p.label }}</NuxtLink>
<Divider />
<NuxtLink @click="logOut()">Kijelentkezés</NuxtLink>
</div>
</div>
</div>
<Button variant="link" icon="pi pi-calendar" @click="$router.push({ path: '/' })"></Button>
<Button variant="link" icon="pi pi-user" @click="$router.push({ path: '/profile' })"></Button>
<Button variant="link" icon="pi pi-bars" @click="openMenu"></Button>
</div>
<div v-if="props.title">
{{ props.title }}
</div>
</div>
<div class="h-12"></div>
</template>
<script lang="ts" setup>
const props = defineProps({
home: {
type: Boolean,
default: true
},
menu: {
type: Boolean,
default: true,
},
title: {
type: String,
default: ''
}
})
const route = useRoute()
const auth = useAuthStore()
const config = useMyConfigStore()
const token = useCookie('_auth')
const router = useRouter()
const isHome = computed(() => {
return (route.fullPath === '/')
})
// Drawer constants
const DRAWER_WIDTH = 288
const SWIPE_THRESHOLD = 80
const EDGE_ZONE = 40
// Simple state
const drawerRef = ref<HTMLElement | null>(null)
const isOpen = ref(false)
const isDragging = ref(false)
const dragOffset = ref(0) // 0 = fully open position, DRAWER_WIDTH = fully closed
const menuHistoryPushed = ref(false)
// Touch tracking
let touchStartX = 0
let touchStartY = 0
let startedFromEdge = false
let isHorizontalSwipe: boolean | null = null
// Computed translate value
const translateX = computed(() => {
if (isDragging.value) {
return Math.max(0, Math.min(DRAWER_WIDTH, dragOffset.value))
}
return isOpen.value ? 0 : DRAWER_WIDTH
})
// Backdrop opacity based on position
const backdropOpacity = computed(() => {
const openness = 1 - (translateX.value / DRAWER_WIDTH)
return openness * 0.5
})
// Dynamic classes and styles
const drawerClass = computed(() => ({
'transition-transform duration-300 ease-out': !isDragging.value,
'pointer-events-none': !isOpen.value && !isDragging.value
}))
const drawerStyle = computed(() => ({
transform: `translateX(${translateX.value}px)`,
visibility: (!isOpen.value && !isDragging.value) ? 'hidden' as const : 'visible' as const
}))
const backdropClass = computed(() => ({
'transition-opacity duration-300': !isDragging.value,
'pointer-events-none': backdropOpacity.value <= 0
}))
function openMenu() {
isOpen.value = true
if (!menuHistoryPushed.value) {
window.history.pushState({ menuOpen: true }, '')
menuHistoryPushed.value = true
}
}
function closeMenu() {
isOpen.value = false
if (menuHistoryPushed.value) {
menuHistoryPushed.value = false
window.history.back()
}
}
function closeMenuWithoutHistory() {
isOpen.value = false
menuHistoryPushed.value = false
}
function handlePopState() {
if (isOpen.value) {
closeMenuWithoutHistory()
}
}
function handleTouchStart(e: TouchEvent) {
const touch = e.touches[0]
touchStartX = touch.clientX
touchStartY = touch.clientY
isHorizontalSwipe = null
const screenWidth = window.innerWidth
startedFromEdge = touchStartX > screenWidth - EDGE_ZONE
if (isOpen.value) {
dragOffset.value = 0
} else if (startedFromEdge) {
dragOffset.value = DRAWER_WIDTH
}
}
function handleTouchMove(e: TouchEvent) {
if (!isOpen.value && !startedFromEdge) return
const touch = e.touches[0]
const deltaX = touch.clientX - touchStartX
const deltaY = touch.clientY - touchStartY
// Determine swipe direction on first significant movement
if (isHorizontalSwipe === null && (Math.abs(deltaX) > 10 || Math.abs(deltaY) > 10)) {
isHorizontalSwipe = Math.abs(deltaX) > Math.abs(deltaY)
}
if (!isHorizontalSwipe) return
// Start dragging
if (!isDragging.value) {
if (isOpen.value && deltaX > 0) {
isDragging.value = true
} else if (startedFromEdge && deltaX < 0) {
isDragging.value = true
}
}
if (isDragging.value) {
if (isOpen.value) {
// Dragging to close: deltaX > 0 means moving right
dragOffset.value = Math.max(0, deltaX)
} else {
// Dragging to open: deltaX < 0 means moving left
dragOffset.value = DRAWER_WIDTH + deltaX
}
}
}
function handleTouchEnd() {
if (!isDragging.value) {
startedFromEdge = false
isHorizontalSwipe = null
return
}
const currentOffset = dragOffset.value
if (isOpen.value) {
// Was open - check if should close
if (currentOffset > SWIPE_THRESHOLD) {
closeMenu()
}
} else {
// Was closed - check if should open
if (currentOffset < DRAWER_WIDTH - SWIPE_THRESHOLD) {
openMenu()
}
}
// Reset
isDragging.value = false
startedFromEdge = false
isHorizontalSwipe = null
}
onMounted(() => {
document.addEventListener('touchstart', handleTouchStart, { passive: true })
document.addEventListener('touchmove', handleTouchMove, { passive: true })
document.addEventListener('touchend', handleTouchEnd, { passive: true })
window.addEventListener('popstate', handlePopState)
})
onUnmounted(() => {
document.removeEventListener('touchstart', handleTouchStart)
document.removeEventListener('touchmove', handleTouchMove)
document.removeEventListener('touchend', handleTouchEnd)
window.removeEventListener('popstate', handlePopState)
})
async function logOut() {
await auth.logout()
}
</script>
<style lang="scss"></style>

90
components/Birthday.vue Normal file
View File

@ -0,0 +1,90 @@
<template>
<div class="w-full flex justify-between">
<select class="bg-transparent" style="outline: none;" v-model="YY">
<option class="dark:bg-black opacity-30" value="">év</option>
<option :value="y" v-for="y in years" class="dark:bg-black">{{ y }}</option>
</select>
<select class="bg-transparent" style="outline: none;" placeholder="hónap" v-model="MM">
<option class="dark:bg-black" value="">hónap</option>
<option :value="m" v-for="m in months" class="dark:bg-black">{{ getMonthName(m) }}</option>
</select>
<select class="bg-transparent" style="outline: none;" v-model="DD">
<option class="dark:bg-black" value="">nap</option>
<option :value="d" v-for="d in days" class="dark:bg-black">{{ d }}</option>
</select>
</div>
</template>
<script lang="ts" setup>
const YY = ref('')
const MM = ref('')
const DD = ref('')
const props = defineProps<{
modelValue?: string
}>()
const emits = defineEmits(['update:model-value'])
watch(() => props.modelValue, (newVal) => {
if (newVal && !YY.value && !MM.value && !DD.value) {
const parts = newVal.split('-')
if (parts.length === 3) {
YY.value = parts[0]
MM.value = parseInt(parts[1], 10).toString()
DD.value = parseInt(parts[2], 10).toString()
}
}
}, { immediate: true })
const years = computed(() => {
let d = new Date()
let i: any
let a = []
for (i = d.getFullYear() - 108; i < d.getFullYear() - 18; i++) {
a.push(i)
}
return a.sort((a, b) => {
return b - a
})
})
const months = computed(() => {
let a = []
let i: any
for (i = 1; i < 13; i++) {
a.push(i)
}
return a
})
const days = computed(() => {
if (YY.value && MM.value) {
let list = new Date(YY.value, MM.value, 0).getDate()
return list
}
})
function getMonthName(m: any) {
let a = ['', 'Január', 'Február', 'Március', 'Április', 'Május', 'Június', 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December']
return a[m]
}
onUpdated(() => {
let date
if (YY.value && MM.value && DD.value) {
date = YY.value
date += '-'
let _m = MM.value + ''
_m = _m.padStart(2, '0')
date += _m
date += '-'
let _d = DD.value + ''
_d = _d.padStart(2, '0')
date += _d
}
if (date) {
emits('update:model-value',date)
}
})
</script>
<style></style>

View File

@ -0,0 +1,11 @@
<template>
<div class="card-loading">
<ProgressSpinner style="width: 32px; height: 32px;" stroke-width="4" />
</div>
</template>
<script lang="ts" setup>
</script>
<style></style>

53
components/Countdown.vue Normal file
View File

@ -0,0 +1,53 @@
<template>
<span>
{{ minutes }}:{{ seconds }}
</span>
</template>
<script setup type="ts">
const minutes = ref()
const seconds = ref()
const interval = ref()
const props = defineProps(['expired'])
const emits = defineEmits(['end'])
const tmp = ref()
function startCountdown() {
let now = new Date()
const end = new Date(props.expired)
console.log(end)
let diff = (end.getTime() - now.getTime()) / 1000
minutes.value = Math.floor(diff / 60)
seconds.value = Math.floor(diff - (minutes.value * 60))
if (seconds.value < 10) {
seconds.value = (seconds.value + '').padStart(2, '0')
}
interval.value = setInterval(() => {
now = new Date()
let diff = (end.getTime() - now.getTime()) / 1000
minutes.value = Math.floor(diff / 60)
seconds.value = Math.floor(diff - (minutes.value * 60))
if (seconds.value < 10) {
seconds.value = (seconds.value + '').padStart(2, '0')
}
if (diff <= 0) {
clearInterval(interval.value)
minutes.value = '0'
seconds.value = '00'
emits('end')
}
}, 1000)
}
onMounted(() => {
startCountdown()
})
onBeforeUnmount(() => {
clearInterval(interval.value)
})
</script>

36
components/Logo.vue Normal file
View File

@ -0,0 +1,36 @@
<template>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 202.3 80.17">
<g id="Réteg_2" data-name="Réteg 2">
<g id="Réteg_3" data-name="Réteg 3">
<path fill="#c7081c" d="M62.38,13.84c24.6,1.92,49.2,2.31,73.58,5.39l-.07,1c-10.16-.54-20.31-1.17-30.47-1.58-14.48-.59-29-.93-43.44-1.55-4-.18-9,.54-12.16,4.58h-4.4a23.91,23.91,0,0,1,3-3.71c-14.46.63-32.08,3-40.75,12.71L23.5,30.4c7.85-5.51,18.09-5.6,24.71,3.84l-3.92-.06c-6-6.45-12.38-5.89-17.31-2.45-2.46,1.72-3.48,2.45-3.48,2.45H0c.16-3.91,2.19-6.53,4.76-8.56,7.92-6.26,17.32-8.86,27-10.33,7.27-1.09,14.65-1.43,22-2.19a10.12,10.12,0,0,0,3.73-1A97.19,97.19,0,0,1,102.81,0c20.17-.48,39.6,3.43,58.55,9.73,10.49,3.48,21.86,8.84,32.13,13,.95.38-.29,1.21-1,.9A308.41,308.41,0,0,0,132,5.17C119,2.68,111,2.52,97.77,3,86.62,3.37,71.89,7.76,62.38,13.84Z"/>
<path :fill="textColor" d="M4,42.91H7.72q3.62,0,7.5-.06l.11.12-.92,5L13.6,48l-.95-3.62H6.89v7.91h.8l2.79,0a.52.52,0,0,0,.5-.41l.54-2,1,0c0,1.44,0,2.52,0,3.23s0,1.76,0,3.18l-1,.08L11,54.2a.5.5,0,0,0-.46-.42l-2.83,0H6.89v5.11q0,1.64,0,3.24h5.95l1.88-3.91.91-.14-.36,5.57-.11.1q-3.7,0-7.21,0H4c-1.28,0-2.6,0-4,0L0,63l2-.55A.5.5,0,0,0,2.4,62c0-.4,0-.84,0-1.33s0-1,0-1.63V47.15c0-.5,0-.95,0-1.36s0-.78,0-1.11A.48.48,0,0,0,2,44.19l-2-.58,0-.76Q2.09,42.91,4,42.91Z"/>
<path :fill="textColor" d="M21.76,42.85c1.38,0,2.91.06,4.58.06s3.26,0,4.59-.06l.07.76-1.93.55a.46.46,0,0,0-.39.44c0,.36,0,.74,0,1.16s0,.85,0,1.33v8.2q0,4.07,1.22,5.62a4.74,4.74,0,0,0,4,1.55,4.94,4.94,0,0,0,4-1.64q1.35-1.65,1.35-5.34V47.09c0-.48,0-.92,0-1.33s0-.8,0-1.16a.46.46,0,0,0-.39-.44l-1.84-.52,0-.79c1.32,0,2.47.06,3.43.06s2,0,3.36-.06l.07.76-2,.58a.48.48,0,0,0-.37.49c0,.33,0,.71,0,1.11s0,.86,0,1.36v7.56q0,5.11-2.11,7.34a8,8,0,0,1-6.12,2.23c-3.05,0-5.29-.71-6.74-2.12s-2.17-3.68-2.17-6.8V47.15c0-.5,0-.95,0-1.36s0-.78,0-1.11a.48.48,0,0,0-.36-.49l-2-.58Z"/>
<path :fill="textColor" d="M56.48,59c0,.59,0,1.13,0,1.6s0,.9,0,1.28.13.52.34.58L58.4,63l.05.74c-1.1,0-2.47,0-4.1,0s-3.28,0-4.64,0L49.64,63l2-.55A.49.49,0,0,0,52,62c0-.4,0-.84,0-1.33s0-1,0-1.63V47.15c0-.5,0-.95,0-1.36s0-.78,0-1.11a.48.48,0,0,0-.35-.49l-2-.58,0-.76c1.39,0,2.81.06,4.27.06l1.14,0,1.67-.05,1.5,0,.94,0a10.45,10.45,0,0,1,5.74,1.28,4.22,4.22,0,0,1,1.91,3.74,5.32,5.32,0,0,1-1.17,3.58,7.46,7.46,0,0,1-3.43,2.09c.83,1.23,1.48,2.22,1.93,3S65,58,65.5,58.7s.87,1.39,1.24,2A8.7,8.7,0,0,0,67.79,62a5.41,5.41,0,0,0,.52.39,4.16,4.16,0,0,0,.51.28,4.77,4.77,0,0,0,.57.2l.68.16.06.75a23.68,23.68,0,0,1-3.34.21,7.64,7.64,0,0,1-2.08-.19,3.44,3.44,0,0,1-1.06-.55,5.93,5.93,0,0,1-1.25-1.4c-.38-.58-.79-1.23-1.22-2s-.86-1.49-1.31-2.31-.93-1.61-1.42-2.41l-.37-.56a1.45,1.45,0,0,0-.28-.34,1,1,0,0,0-.3-.16,1.3,1.3,0,0,0-.39-.07h-.63Zm0-6.27c.53,0,1,0,1.43,0A4,4,0,0,0,61,51.72a4.81,4.81,0,0,0,1-3.32,4.52,4.52,0,0,0-1-3.19,3.86,3.86,0,0,0-2.94-1l-.73,0-.89.09Z"/>
<path :fill="textColor" d="M96.71,52.82a11.38,11.38,0,0,1-3,8.28q-3,3.13-8.45,3.13-5.18,0-8-2.89a10.73,10.73,0,0,1-2.83-7.84,10.89,10.89,0,0,1,3-8.15c2-2,4.85-3,8.44-3s6.12.93,8,2.8A10.28,10.28,0,0,1,96.71,52.82ZM79.39,53c0,3.17.53,5.6,1.61,7.28a5.22,5.22,0,0,0,4.71,2.53,5,5,0,0,0,4.53-2.29q1.47-2.3,1.47-7.21a13.46,13.46,0,0,0-1.55-7.09,5.25,5.25,0,0,0-4.79-2.48,5,5,0,0,0-4.56,2.3C79.86,47.59,79.39,49.9,79.39,53Z"/>
<path :fill="textColor" d="M131.21,48.47l-.82.14-1.13-4.28a8.61,8.61,0,0,0-2.54-.37,5.92,5.92,0,0,0-5.09,2.47,10.67,10.67,0,0,0-1.8,6.45A10.17,10.17,0,0,0,122,59.66a7.24,7.24,0,0,0,5.88,2.53,12.74,12.74,0,0,0,4.42-.85l.2.85a11.71,11.71,0,0,1-6.73,2,10.75,10.75,0,0,1-7.86-2.94,10.29,10.29,0,0,1-3-7.72,10.33,10.33,0,0,1,3.29-8.08,12.31,12.31,0,0,1,8.58-3,25,25,0,0,1,5.36.61l.09.15Z"/>
<path :fill="textColor" d="M143.11,57.07l-1.06,2.79c-.21.54-.37,1-.48,1.31a2.53,2.53,0,0,0-.18.77.53.53,0,0,0,.14.39.91.91,0,0,0,.42.2l1.42.42,0,.77c-1.44,0-2.61,0-3.51,0s-2,0-3.23,0L136.6,63l1.6-.48A1.46,1.46,0,0,0,139,62a6,6,0,0,0,.59-1.15L147,42.76l1.61-.24,6.42,18.09a4.85,4.85,0,0,0,.67,1.41,1.81,1.81,0,0,0,.87.53l1.46.43.05.74c-1.34,0-2.69,0-4.05,0-1.8,0-3.55,0-5.25,0l-.08-.74,1.47-.43a1.06,1.06,0,0,0,.44-.22.56.56,0,0,0,.13-.41,2.88,2.88,0,0,0-.15-.78c-.1-.32-.24-.74-.43-1.27l-1-2.8Zm3.21-8.54c-.18.52-.37,1-.58,1.61l-2,5.39h5l-1.83-5.38C146.65,49.59,146.48,49.05,146.32,48.53Z"/>
<path :fill="textColor" d="M170,59v1.6c0,.47,0,.9,0,1.28s.12.52.34.58l1.55.51,0,.74c-1.1,0-2.47,0-4.09,0s-3.29,0-4.65,0l-.07-.74,2-.55a.5.5,0,0,0,.41-.46c0-.4,0-.84,0-1.33s0-1,0-1.63V47.15c0-.5,0-.95,0-1.36s0-.78,0-1.11a.48.48,0,0,0-.36-.49l-2-.58,0-.76c1.39,0,2.81.06,4.27.06l1.15,0,1.66-.05,1.5,0,.94,0a10.43,10.43,0,0,1,5.74,1.28,4.2,4.2,0,0,1,1.91,3.74,5.37,5.37,0,0,1-1.16,3.58,7.52,7.52,0,0,1-3.43,2.09c.83,1.23,1.47,2.22,1.92,3S178.52,58,179,58.7s.87,1.39,1.25,2A8.7,8.7,0,0,0,181.27,62a5.34,5.34,0,0,0,.51.39,4.16,4.16,0,0,0,.51.28,4.38,4.38,0,0,0,.58.2l.67.16.06.75a23.53,23.53,0,0,1-3.33.21,7.59,7.59,0,0,1-2.08-.19,3.44,3.44,0,0,1-1.06-.55,5.75,5.75,0,0,1-1.26-1.4c-.38-.58-.79-1.23-1.21-2s-.87-1.49-1.32-2.31-.92-1.61-1.42-2.41l-.36-.56a1.46,1.46,0,0,0-.29-.34.92.92,0,0,0-.29-.16,1.44,1.44,0,0,0-.4-.07H170Zm0-6.27c.52,0,1,0,1.42,0a4,4,0,0,0,3.1-1.07,4.81,4.81,0,0,0,1-3.32,4.52,4.52,0,0,0-.94-3.19,3.86,3.86,0,0,0-2.94-1l-.74,0-.88.09Z"/>
<path :fill="textColor" d="M198.75,44.26a5.55,5.55,0,0,0-2.06-.37,4,4,0,0,0-2.67.92,3,3,0,0,0-1.1,2.38,2.92,2.92,0,0,0,.36,1.5,4,4,0,0,0,.95,1.12,7.4,7.4,0,0,0,1.36.88c.51.26,1,.51,1.59.77s1.21.61,1.83.95a8,8,0,0,1,1.65,1.22,5.4,5.4,0,0,1,1.18,1.69,5.52,5.52,0,0,1,.46,2.38A5.62,5.62,0,0,1,200,62.44a9.64,9.64,0,0,1-6,1.73,17,17,0,0,1-5.31-.85l-.09-.13.78-5.36.93-.15,1.11,4.56a5.79,5.79,0,0,0,2.38.49,4.62,4.62,0,0,0,3.05-1A3.17,3.17,0,0,0,198,59.2a3.08,3.08,0,0,0-.36-1.54,3.94,3.94,0,0,0-1-1.13,7.7,7.7,0,0,0-1.39-.89l-1.6-.77c-.61-.3-1.22-.61-1.82-.94a6.65,6.65,0,0,1-1.62-1.19,5.26,5.26,0,0,1-1.16-1.67,5.61,5.61,0,0,1-.45-2.36,5.4,5.4,0,0,1,2.17-4.52,8.91,8.91,0,0,1,5.64-1.69,21.38,21.38,0,0,1,5,.69l.09.13-.91,4.79-.82.14Z"/>
<path :fill="textColor" d="M54.81,77.56v.8c0,.24,0,.45,0,.65a.29.29,0,0,0,.18.29l.77.25,0,.37-2,0-2.33,0,0-.37,1-.27a.25.25,0,0,0,.2-.24c0-.19,0-.42,0-.66V71c0-.21,0-.39,0-.56a.24.24,0,0,0-.17-.25l-1-.29,0-.38q1,0,2.13,0h.58l.83,0,.75,0h.47a5.19,5.19,0,0,1,2.87.64A2.11,2.11,0,0,1,60,72a2.64,2.64,0,0,1-.58,1.79,3.61,3.61,0,0,1-1.72,1.05c.42.61.74,1.11,1,1.49s.45.76.68,1.13.43.7.62,1a4.77,4.77,0,0,0,.52.67l.26.19a.94.94,0,0,0,.26.14l.28.11.34.07,0,.38a11.63,11.63,0,0,1-1.66.11,4,4,0,0,1-1-.1,1.83,1.83,0,0,1-.52-.27,3.07,3.07,0,0,1-.63-.7c-.19-.29-.4-.62-.61-1l-.66-1.15c-.22-.41-.46-.81-.71-1.21l-.18-.28a.9.9,0,0,0-.14-.17l-.15-.08a.56.56,0,0,0-.2,0h-.31Zm0-3.13c.26,0,.5,0,.71,0a2,2,0,0,0,1.55-.53,2.37,2.37,0,0,0,.49-1.66,2.32,2.32,0,0,0-.47-1.6,2,2,0,0,0-1.47-.5l-.37,0-.44,0Z"/>
<path :fill="textColor" d="M65.33,69.51h1.88l3.75,0,.05.06L70.55,72l-.4.06-.48-1.81H66.8v4h1.79a.26.26,0,0,0,.25-.2l.27-1,.49,0c0,.72,0,1.25,0,1.61s0,.88,0,1.59l-.49,0-.28-1A.25.25,0,0,0,68.6,75H66.8v2.55c0,.55,0,1.09,0,1.62h3l.93-2,.46-.07L71,79.87l0,0-3.61,0h-2l-2,0,0-.37,1-.27a.27.27,0,0,0,.2-.24c0-.19,0-.42,0-.66V71c0-.21,0-.39,0-.56a.26.26,0,0,0-.18-.25l-1-.29,0-.38Z"/>
<path :fill="textColor" d="M75.76,79a.25.25,0,0,0,.19.26l1,.26,0,.38-1.65,0-1.68,0,0-.37,1-.27a.26.26,0,0,0,.21-.24c0-.4,0-.89,0-1.48V71.63c0-.49,0-.9,0-1.23a.26.26,0,0,0-.18-.25l-1-.29,0-.38,1.6,0q.72,0,1.38,0l4.95,6.2.61.79c0-.34,0-.67,0-1V71.6c0-.48,0-.89,0-1.24a.23.23,0,0,0-.19-.22l-1-.26,0-.4,1.67,0,1.66,0,0,.38-1,.29a.26.26,0,0,0-.18.25c0,.33,0,.74,0,1.23V79.9L82.2,80l-5.87-7.34-.6-.8c0,.37,0,.71,0,1v4.71C75.75,78.15,75.75,78.63,75.76,79Z"/>
<path :fill="textColor" d="M90.6,79.9l-2.5,0,0-.37,1.19-.33a.25.25,0,0,0,.19-.23c0-.38,0-.86,0-1.44V70.28H87.32l-.68,2-.42.07L86,69.54l0-.06,3.5,0h2.08l3.53,0,0,.06-.49,2.73-.42.06-.48-2H91.69v7.27c0,.58,0,1.06,0,1.44a.26.26,0,0,0,.21.23l1.16.33,0,.37Z"/>
<path :fill="textColor" d="M103.67,76.6,103.15,78c-.11.27-.19.49-.25.66a1.43,1.43,0,0,0-.08.38.24.24,0,0,0,.07.19.42.42,0,0,0,.2.11l.72.21,0,.38-1.76,0-1.61,0,0-.37.8-.24a.71.71,0,0,0,.42-.27,4.14,4.14,0,0,0,.29-.57l3.71-9,.8-.12,3.21,9.05a2.36,2.36,0,0,0,.34.7.89.89,0,0,0,.43.27l.73.21,0,.37-2,0-2.63,0,0-.37.73-.21a.51.51,0,0,0,.22-.12.28.28,0,0,0,.07-.2,1.41,1.41,0,0,0-.08-.39l-.21-.63-.5-1.4Zm1.61-4.27c-.09.25-.18.52-.29.8l-1,2.69h2.49l-.92-2.68Z"/>
<path :fill="textColor" d="M125.82,72.3l-.41.06-.57-2.13a4,4,0,0,0-1.27-.19A3,3,0,0,0,121,71.27a5.35,5.35,0,0,0-.9,3.23,5.13,5.13,0,0,0,1.06,3.39,3.63,3.63,0,0,0,2.95,1.27,6.31,6.31,0,0,0,2.21-.43l.09.43a5.86,5.86,0,0,1-3.36,1,5.37,5.37,0,0,1-3.93-1.47,5.14,5.14,0,0,1-1.5-3.86,5.19,5.19,0,0,1,1.64-4,6.18,6.18,0,0,1,4.3-1.49,11.84,11.84,0,0,1,2.67.31l0,.07Z"/>
<path :fill="textColor" d="M131,76.6,130.47,78l-.24.66a1.18,1.18,0,0,0-.09.38.27.27,0,0,0,.07.19.52.52,0,0,0,.21.11l.71.21,0,.38-1.76,0-1.61,0,0-.37.8-.24A.71.71,0,0,0,129,79a3.17,3.17,0,0,0,.3-.57l3.71-9,.8-.12L137,78.37a2.4,2.4,0,0,0,.33.7,1,1,0,0,0,.44.27l.73.21,0,.37-2,0-2.63,0,0-.37.74-.21a.51.51,0,0,0,.22-.12.28.28,0,0,0,.06-.2,1.34,1.34,0,0,0-.07-.39c0-.16-.12-.37-.22-.63l-.49-1.4Zm1.61-4.27-.29.8-1,2.69h2.48l-.91-2.68C132.77,72.85,132.69,72.58,132.61,72.33Z"/>
<path :fill="textColor" d="M143.66,77.56c0,.3,0,.57,0,.8s0,.45,0,.65a.27.27,0,0,0,.17.29l.77.25,0,.37-2.05,0-2.32,0,0-.37,1-.27a.27.27,0,0,0,.2-.24c0-.19,0-.42,0-.66V71c0-.21,0-.39,0-.56a.26.26,0,0,0-.18-.25l-1-.29,0-.38c.69,0,1.41,0,2.14,0H143l.83,0,.75,0H145a5.17,5.17,0,0,1,2.87.64,2.09,2.09,0,0,1,1,1.86,2.65,2.65,0,0,1-.59,1.79,3.62,3.62,0,0,1-1.71,1.05c.41.61.74,1.11,1,1.49s.45.76.68,1.13l.62,1a4.11,4.11,0,0,0,.53.67c.09.07.17.14.25.19a1.1,1.1,0,0,0,.26.14l.29.11.34.07,0,.38a11.89,11.89,0,0,1-1.67.11,4,4,0,0,1-1-.1,1.76,1.76,0,0,1-.53-.27,3.07,3.07,0,0,1-.63-.7c-.19-.29-.39-.62-.61-1s-.43-.75-.65-1.15-.47-.81-.71-1.21l-.19-.28a.49.49,0,0,0-.14-.17l-.15-.08a.54.54,0,0,0-.19,0h-.32Zm0-3.13c.27,0,.5,0,.72,0a2,2,0,0,0,1.55-.53,2.42,2.42,0,0,0,.49-1.66,2.27,2.27,0,0,0-.48-1.6,1.93,1.93,0,0,0-1.47-.5l-.36,0-.45,0Z"/>
<path :fill="lineColor" d="M23.29,72.68H45.15V75H.24S16,72.68,23.29,72.68Z"/>
<path :fill="lineColor" d="M179,72.68H157.15V75h44.91S186.26,72.68,179,72.68Z"/>
</g>
</g>
</svg>
</template>
<script setup lang="ts">
const props = defineProps<{
dark?: boolean
}>()
const textColor = computed(() => props.dark ? '#e0e0e0' : '#1a1a1a')
const lineColor = computed(() => props.dark ? '#a5a5a5' : '#4a4a4a')
</script>

View File

@ -0,0 +1,13 @@
<template>
<Teleport to="#teleports">
<div class="card-loading" style="position: fixed;">
<ProgressSpinner style="width: 48px; height: 48px;" stroke-width="6" />
</div>
</Teleport>
</template>
<script lang="ts" setup>
</script>
<style></style>

View File

@ -0,0 +1,26 @@
<template>
<div
class="pull-indicator fixed left-1/2 -translate-x-1/2 z-50 transition-all duration-200"
:style="{ top: `${Math.max(pullDistance - 40, -40)}px`, opacity: pullDistance / threshold }"
>
<div
class="w-10 h-10 bg-white rounded-full shadow-lg flex items-center justify-center"
:class="{ 'animate-spin': isRefreshing }"
>
<i
class="pi text-neutral-600"
:class="isRefreshing ? 'pi-spinner' : (pullDistance >= threshold ? 'pi-check' : 'pi-arrow-down')"
></i>
</div>
</div>
</template>
<script setup lang="ts">
const emit = defineEmits<{
refresh: []
}>()
const { pullDistance, isRefreshing, threshold } = usePullToRefresh(async () => {
emit('refresh')
})
</script>

28
components/RentStep.vue Normal file
View File

@ -0,0 +1,28 @@
<template>
<div class="flex gap-2 p-3 w-full justify-between h-1 fixed bg-surface-50 dark:bg-surface-950 top-12">
<div v-for="i in 8" :class="inidactorClass(i)" style="padding: 2px;">
</div>
</div>
<div class="h-7"></div>
</template>
<script lang="ts" setup>
const router = useRouter()
const route = useRoute()
const rentList = computed(() => {
let r = router.getRoutes()
return r.filter(x => { if (x.path = '/rent' && x.children.length > 0 && x.children[0].name?.toString().match(/^rent-/gi)) { return true } }).map(x => { return x.children })[0].sort((a, b) => a.meta.rentStep - b.meta.rentStep)
})
const inidactorClass = (n)=>{
let a = ['w-full']
if(n <= route.meta?.rentStep){
a.push('bg-primary dark:bg-primary')
}else{
a.push('bg-gray-300 dark:bg-stone-800')
}
return a
}
</script>
<style></style>

View File

@ -0,0 +1,49 @@
<template>
<div class="space-y-3">
<FloatLabel variant="on">
<Select v-model="cim.orszag" inputId="orszag" :options="config.countries" option-value="iso_code_2"
optionLabel="name_hu" class="w-full" filter resetFilterOnHide resetFilterOnClear autoFilterFocus />
<label for="orszag">Ország</label>
</FloatLabel>
<div class="flex gap-2">
<FloatLabel variant="on" class="w-1/3">
<InputText id="tartozkodasicim" v-model="cim.iranyitoszam" class="w-full" :invalid="!cim.iranyitoszam" />
<label for="tartozkodasicim">Irányítószám</label>
</FloatLabel>
<FloatLabel variant="on" class="w-2/3">
<InputText id="tartozkodasicim" v-model="cim.telepules" class="w-full" :invalid="!cim.telepules" />
<label for="tartozkodasicim">Település</label>
</FloatLabel>
</div>
<FloatLabel variant="on">
<InputText id="tartozkodasicim" v-model="cim.cim" class="w-full" :invalid="!cim.cim" />
<label for="tartozkodasicim">Utca (közterület)</label>
</FloatLabel>
<div class="flex gap-2">
<FloatLabel variant="on">
<InputText id="tartozkodasicim" v-model="cim.hazszam" class="w-full" :invalid="!cim.hazszam" />
<label for="tartozkodasicim">Házszám</label>
</FloatLabel>
<FloatLabel variant="on">
<InputText id="tartozkodasicim" v-model="cim.emajto" class="w-full" />
<label for="tartozkodasicim">Emelet/ajtó</label>
</FloatLabel>
</div>
</div>
</template>
<script lang="ts" setup>
const config = useMyConfigStore()
const value = defineModel()
const cim = ref({
iranyitoszam: '',
telepules: '',
cim: '',
hazszam: '',
emajto: '',
orszag: 'HU'
})
</script>
<style lang="scss"></style>

View File

@ -0,0 +1,10 @@
export const useLocaleDateString = (d:any) => {
let _d = d
if(typeof d === "string"){
let _d = new Date(d)
}
if(typeof _d === 'object'){
console.log(typeof _d)
return _d.toLocaleDateString()
}
}

43
composables/useApi.ts Normal file
View File

@ -0,0 +1,43 @@
/**
* Központi API composable
* Az összes API hívás ezen keresztül történik
*/
export const useApi = () => {
const config = useRuntimeConfig()
const baseUrl = config.public.apiBase as string
/**
* API végpont URL összeállítása
*/
const getUrl = (endpoint: string): string => {
// Ha már teljes URL, visszaadjuk
if (endpoint.startsWith('http')) {
return endpoint
}
// Biztosítjuk, hogy az endpoint /-vel kezdődjön
const path = endpoint.startsWith('/') ? endpoint : `/${endpoint}`
return `${baseUrl}${path}`
}
/**
* useFetch wrapper az API hívásokhoz
*/
const apiFetch = <T>(endpoint: string, options?: Parameters<typeof useFetch>[1]) => {
return useFetch<T>(getUrl(endpoint), options)
}
/**
* $fetch wrapper az API hívásokhoz (nem reaktív, közvetlen hívás)
*/
const apiRequest = <T>(endpoint: string, options?: Parameters<typeof $fetch>[1]) => {
return $fetch<T>(getUrl(endpoint), options)
}
return {
baseUrl,
getUrl,
apiFetch,
apiRequest
}
}

View File

@ -0,0 +1,45 @@
const AUTH_KEY = '_auth'
export const useAuthToken = () => {
const token = ref<string | null>(null)
const isLoaded = ref(false)
// Token betöltése - LocalStorage (működik web + native)
const loadToken = async (): Promise<string | null> => {
if (typeof window === 'undefined') return null
token.value = localStorage.getItem(AUTH_KEY)
isLoaded.value = true
return token.value
}
// Token mentése
const setToken = async (newToken: string): Promise<void> => {
if (typeof window === 'undefined') return
token.value = newToken
localStorage.setItem(AUTH_KEY, newToken)
}
// Token törlése (kijelentkezés)
const clearToken = async (): Promise<void> => {
if (typeof window === 'undefined') return
token.value = null
localStorage.removeItem(AUTH_KEY)
}
// Getter a token értékhez
const getToken = (): string | null => {
return token.value
}
return {
token: readonly(token),
isLoaded: readonly(isLoaded),
loadToken,
setToken,
clearToken,
getToken
}
}

View File

@ -0,0 +1,63 @@
export function usePullToRefresh(onRefresh: () => Promise<void> | void) {
const isPulling = ref(false)
const pullDistance = ref(0)
const isRefreshing = ref(false)
const threshold = 80
let startY = 0
let currentY = 0
const onTouchStart = (e: TouchEvent) => {
if (window.scrollY === 0) {
startY = e.touches[0].clientY
isPulling.value = true
}
}
const onTouchMove = (e: TouchEvent) => {
if (!isPulling.value || isRefreshing.value) return
currentY = e.touches[0].clientY
const diff = currentY - startY
if (diff > 0 && window.scrollY === 0) {
pullDistance.value = Math.min(diff * 0.5, threshold * 1.5)
if (diff > 10) {
e.preventDefault()
}
}
}
const onTouchEnd = async () => {
if (!isPulling.value) return
if (pullDistance.value >= threshold && !isRefreshing.value) {
isRefreshing.value = true
await onRefresh()
isRefreshing.value = false
}
isPulling.value = false
pullDistance.value = 0
startY = 0
}
onMounted(() => {
document.addEventListener('touchstart', onTouchStart, { passive: true })
document.addEventListener('touchmove', onTouchMove, { passive: false })
document.addEventListener('touchend', onTouchEnd)
})
onUnmounted(() => {
document.removeEventListener('touchstart', onTouchStart)
document.removeEventListener('touchmove', onTouchMove)
document.removeEventListener('touchend', onTouchEnd)
})
return {
isPulling,
pullDistance,
isRefreshing,
threshold
}
}

10
ecosystem.config.cjs Normal file
View File

@ -0,0 +1,10 @@
module.exports = {
apps : [{
name : "app1",
script : "serve",
env: {
PM2_SERVE_PATH: './dist',
PM2_SERVE_PORT: 3180
}
}]
}

BIN
icons/icon-128.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
icons/icon-192.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
icons/icon-256.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
icons/icon-48.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
icons/icon-512.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
icons/icon-72.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
icons/icon-96.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -0,0 +1,27 @@
export default defineNuxtRouteMiddleware(async(to, from) => {
const authStore = useAuthStore()
const token = useCookie('_auth')
await authStore.getData()
let navigate: any = false
/** Belépett */
if (authStore.user) {
if (to.fullPath.match(/^\/login/gi)) {
navigate = '/'
}
} else {
navigate = '/login'
if (to.fullPath.match(/^\/login/gi)) {
navigate = false
}
if (to.fullPath.match(/^\/page/gi)) {
navigate = false
}
}
if (navigate) {
return navigateTo(navigate)
}
})

View File

@ -0,0 +1,53 @@
export default defineNuxtRouteMiddleware(async (to, from) => {
const authStore = useAuthStore()
// Csak bejelentkezett felhasználóknál ellenőrzünk
if (!authStore.user) {
return
}
// Ha már a profil oldalon vagyunk, ne irányítsunk át (végtelen loop elkerülése)
if (to.fullPath.match(/^\/profile/gi)) {
return
}
// Login és page oldalak kihagyása
if (to.fullPath.match(/^\/login/gi) || to.fullPath.match(/^\/page/gi)) {
return
}
// Kötelező mezők listája
const requiredFields = [
'nev',
'email',
'telefon',
'anyja_neve',
'szuletesi_hely',
'szuletesi_ido',
'nemzetiseg',
'szigszam',
'jogositvany_szama',
'lakcim'
] as const
const user = authStore.user as Record<string, any>
// Ellenőrizzük, hogy minden kötelező mező ki van-e töltve
const missingFields = requiredFields.filter(field => {
const value = user[field]
return !value || (typeof value === 'string' && value.trim() === '')
})
// Ha van hiányzó mező, átirányítjuk a profil oldalra
if (missingFields.length > 0) {
return navigateTo('/profile')
}
// Ha foglalás oldalon vagyunk
if (to.fullPath.match(/^\/rent/gi)) {
// console.log(authStore.rent)
// if(!authStore.rent?.auto_felvetel_datum){
// return navigateTo('/rent/date-from')
// }
}
})

View File

@ -1,205 +1,222 @@
import * as path from "path";
export default defineNuxtConfig({
compatibilityDate:'2024-12-29',
modules: [ "@primevue/nuxt-module"],
css: ['@/assets/styles/tailwind.css', '@/assets/styles/base.css'],
primevue: {
options: { theme: 'none' , locale:{
"accept": "Igen",
"addRule": "Szabály hozzáadása",
"am": "de.",
"apply": "Alkalmaz",
"cancel": "Mégsem",
"choose": "Kiválaszt",
"chooseDate": "Válassz dátumot",
"chooseMonth": "Válassz hónapot",
"chooseYear": "Válassz évet",
"clear": "Törlés",
"completed": "Befejezve",
"contains": "Tartalmazza",
"custom": "Egyedi",
"dateAfter": "Dátum későbbi",
"dateBefore": "Dátum korábbi",
"dateFormat": "yy.mm.dd",
"dateIs": "Dátum egyenlő",
"dateIsNot": "Dátum nem egyenlő",
"dayNames": [
"vasárnap",
"hétfő",
"kedd",
"szerda",
"csütörtök",
"péntek",
"szombat"
],
"dayNamesMin": [
"V",
"H",
"K",
"Sz",
"Cs",
"P",
"Sz"
],
"dayNamesShort": [
"V",
"H",
"K",
"Sze",
"Cs",
"P",
"Szo"
],
"emptyFilterMessage": "Nincs találat",
"emptyMessage": "Nincs elérhető opció",
"emptySearchMessage": "Nincs találat",
"emptySelectionMessage": "Nincs kijelölt elem",
"endsWith": "Ezzel végződik",
"equals": "Egyenlő",
"fileSizeTypes": [
"B",
"KB",
"MB",
"GB",
"TB",
"PB",
"EB",
"ZB",
"YB"
],
"filter": "Szűrő",
"firstDayOfWeek": 1,
"gt": "Nagyobb",
"gte": "Nagyobb vagy egyenlő",
"lt": "Kisebb",
"lte": "Kisebb vagy egyenlő",
"matchAll": "Megfelel mindegyiknek",
"matchAny": "Megfelel bármelyiknek",
"medium": "Közepes",
"monthNames": [
"január",
"február",
"március",
"április",
"május",
"június",
"július",
"augusztus",
"szeptember",
"október",
"november",
"december"
],
"monthNamesShort": [
"jan.",
"febr.",
"márc.",
"ápr.",
"máj.",
"jún.",
"júl.",
"aug.",
"szept.",
"okt.",
"nov.",
"dec."
],
"nextDecade": "Következő évtized",
"nextHour": "Következő óra",
"nextMinute": "Következő perc",
"nextMonth": "Következő hónap",
"nextSecond": "Következő másodperc",
"nextYear": "Következő év",
"noFilter": "Nincs szűrő",
"notContains": "Nem tartalmazza",
"notEquals": "Nem egyenlő",
"now": "Most",
"passwordPrompt": "Jelszó megadása",
"pending": "Függőben",
"pm": "du.",
"prevDecade": "Előző évtized",
"prevHour": "Előző óra",
"prevMinute": "Előző perc",
"prevMonth": "Előző hónap",
"prevSecond": "Előző másodperc",
"prevYear": "Előző év",
"reject": "Nem",
"removeRule": "Szabály eltávolítása",
"searchMessage": "{0} találat érhető el",
"selectionMessage": "{0} elem kijelölve",
"showMonthAfterYear": true,
"startsWith": "Ezzel kezdődik",
"strong": "Erős",
"today": "Ma",
"upload": "Feltölt",
"weak": "Gyenge",
"weekHeader": "Hét",
"aria": {
"cancelEdit": "Szerkesztés elvetése",
"close": "Bezár",
"collapseLabel": "Összeomlás",
"collapseRow": "Sor összecsukva",
"editRow": "Sor szerkesztése",
"expandLabel": "Kiterjed",
"expandRow": "Sor lenyitva",
"falseLabel": "Hamis",
"filterConstraint": "Szűrési feltétel",
"filterOperator": "Szűrési logikai operátor",
"firstPageLabel": "Első oldal",
"gridView": "Rács nézet",
"hideFilterMenu": "Szűrő menü elrejtése",
"jumpToPageDropdownLabel": "Ugrás az oldal kiválasztó legördülő menühöz",
"jumpToPageInputLabel": "Ugrás az oldal számát megadó beviteli mezőhöz",
"lastPageLabel": "Utolsó oldal",
"listView": "Lista nézet",
"moveAllToSource": "Minden mozgatása a forráshoz",
"moveAllToTarget": "Minden mozgatása a célhoz",
"moveBottom": "Mozgatás az aljára",
"moveDown": "Mozgatás lejjebb",
"moveTop": "Mozgatás a tetejére",
"moveToSource": "Mozgatás a forráshoz",
"moveToTarget": "Mozgatás a célhoz",
"moveUp": "Mozgatás feljebb",
"navigation": "Navigáció",
"next": "Következő",
"nextPageLabel": "Következő oldal",
"nullLabel": "Nincs kijelölve",
"otpLabel": "Kérjük, írjon be egyszeri jelszó karaktert: {0}",
"pageLabel": "{page}. oldal",
"passwordHide": "Jelszó elrejtése",
"passwordShow": "Mutasd a jelszót",
"previous": "Előző",
"previousPageLabel": "Előző oldal",
"removeLabel": "Távolítsa el",
"rotateLeft": "Forgatás balra",
"rotateRight": "Forgatás jobbra",
"rowsPerPageLabel": "Sorok száma egy oldalon",
"saveEdit": "Szerkesztés mentése",
"scrollTop": "Görgetés a tetejére",
"selectAll": "Összes elem kijelölve",
"selectLabel": "Válassza ki",
"selectRow": "Sor kijelölve",
"showFilterMenu": "Szűrő menü megjelenítése",
"slide": "Dia",
"slideNumber": "{slideNumber}",
"star": "1 csillag",
"stars": "{star} csillag",
"trueLabel": "Igaz",
"unselectAll": "Nincs elem kijelölve",
"unselectLabel": "Törölje a kijelölést",
"unselectRow": "Sor nincs kijelölve",
"zoomImage": "Kép nagyítása",
"zoomIn": "Nagyítás",
"zoomOut": "Kicsinyítés"
}
}},
},
postcss: {
plugins: {
'postcss-import': {},
tailwindcss: {},
autoprefixer: {}
}
compatibilityDate: '2024-12-29',
runtimeConfig: {
public: {
apiBase: process.env.NUXT_PUBLIC_API_BASE || 'https://olcsoberauto.hu/rest'
}
});
},
devServer: {
host: '0.0.0.0',
port: 3280
},
ssr: false,
modules: ["@primevue/nuxt-module", "@pinia/nuxt", "@pinia-plugin-persistedstate/nuxt", "@nuxt/icon", "@vite-pwa/nuxt"],
piniaPluginPersistedstate: {
storage: 'localStorage'
},
css: ['@/assets/styles/tailwind.css', '@/assets/styles/base.css', '@/assets/styles/fonts.css'],
primevue: {
options: {
theme: 'none', pt: {
card: { root: 'shadowl-lg', body: 'p-2' }
}, locale: {
"accept": "Igen",
"addRule": "Szabály hozzáadása",
"am": "de.",
"apply": "Alkalmaz",
"cancel": "Mégsem",
"choose": "Kiválaszt",
"chooseDate": "Válassz dátumot",
"chooseMonth": "Válassz hónapot",
"chooseYear": "Válassz évet",
"clear": "Törlés",
"completed": "Befejezve",
"contains": "Tartalmazza",
"custom": "Egyedi",
"dateAfter": "Dátum későbbi",
"dateBefore": "Dátum korábbi",
"dateFormat": "yy.mm.dd",
"dateIs": "Dátum egyenlő",
"dateIsNot": "Dátum nem egyenlő",
"dayNames": [
"vasárnap",
"hétfő",
"kedd",
"szerda",
"csütörtök",
"péntek",
"szombat"
],
"dayNamesMin": [
"V",
"H",
"K",
"Sz",
"Cs",
"P",
"Sz"
],
"dayNamesShort": [
"V",
"H",
"K",
"Sze",
"Cs",
"P",
"Szo"
],
"emptyFilterMessage": "Nincs találat",
"emptyMessage": "Nincs elérhető opció",
"emptySearchMessage": "Nincs találat",
"emptySelectionMessage": "Nincs kijelölt elem",
"endsWith": "Ezzel végződik",
"equals": "Egyenlő",
"fileSizeTypes": [
"B",
"KB",
"MB",
"GB",
"TB",
"PB",
"EB",
"ZB",
"YB"
],
"filter": "Szűrő",
"firstDayOfWeek": 1,
"gt": "Nagyobb",
"gte": "Nagyobb vagy egyenlő",
"lt": "Kisebb",
"lte": "Kisebb vagy egyenlő",
"matchAll": "Megfelel mindegyiknek",
"matchAny": "Megfelel bármelyiknek",
"medium": "Közepes",
"monthNames": [
"január",
"február",
"március",
"április",
"május",
"június",
"július",
"augusztus",
"szeptember",
"október",
"november",
"december"
],
"monthNamesShort": [
"jan.",
"febr.",
"márc.",
"ápr.",
"máj.",
"jún.",
"júl.",
"aug.",
"szept.",
"okt.",
"nov.",
"dec."
],
"nextDecade": "Következő évtized",
"nextHour": "Következő óra",
"nextMinute": "Következő perc",
"nextMonth": "Következő hónap",
"nextSecond": "Következő másodperc",
"nextYear": "Következő év",
"noFilter": "Nincs szűrő",
"notContains": "Nem tartalmazza",
"notEquals": "Nem egyenlő",
"now": "Most",
"passwordPrompt": "Jelszó megadása",
"pending": "Függőben",
"pm": "du.",
"prevDecade": "Előző évtized",
"prevHour": "Előző óra",
"prevMinute": "Előző perc",
"prevMonth": "Előző hónap",
"prevSecond": "Előző másodperc",
"prevYear": "Előző év",
"reject": "Nem",
"removeRule": "Szabály eltávolítása",
"searchMessage": "{0} találat érhető el",
"selectionMessage": "{0} elem kijelölve",
"showMonthAfterYear": true,
"startsWith": "Ezzel kezdődik",
"strong": "Erős",
"today": "Ma",
"upload": "Feltölt",
"weak": "Gyenge",
"weekHeader": "Hét",
"aria": {
"cancelEdit": "Szerkesztés elvetése",
"close": "Bezár",
"collapseLabel": "Összeomlás",
"collapseRow": "Sor összecsukva",
"editRow": "Sor szerkesztése",
"expandLabel": "Kiterjed",
"expandRow": "Sor lenyitva",
"falseLabel": "Hamis",
"filterConstraint": "Szűrési feltétel",
"filterOperator": "Szűrési logikai operátor",
"firstPageLabel": "Első oldal",
"gridView": "Rács nézet",
"hideFilterMenu": "Szűrő menü elrejtése",
"jumpToPageDropdownLabel": "Ugrás az oldal kiválasztó legördülő menühöz",
"jumpToPageInputLabel": "Ugrás az oldal számát megadó beviteli mezőhöz",
"lastPageLabel": "Utolsó oldal",
"listView": "Lista nézet",
"moveAllToSource": "Minden mozgatása a forráshoz",
"moveAllToTarget": "Minden mozgatása a célhoz",
"moveBottom": "Mozgatás az aljára",
"moveDown": "Mozgatás lejjebb",
"moveTop": "Mozgatás a tetejére",
"moveToSource": "Mozgatás a forráshoz",
"moveToTarget": "Mozgatás a célhoz",
"moveUp": "Mozgatás feljebb",
"navigation": "Navigáció",
"next": "Következő",
"nextPageLabel": "Következő oldal",
"nullLabel": "Nincs kijelölve",
"otpLabel": "Kérjük, írjon be egyszeri jelszó karaktert: {0}",
"pageLabel": "{page}. oldal",
"passwordHide": "Jelszó elrejtése",
"passwordShow": "Mutasd a jelszót",
"previous": "Előző",
"previousPageLabel": "Előző oldal",
"removeLabel": "Távolítsa el",
"rotateLeft": "Forgatás balra",
"rotateRight": "Forgatás jobbra",
"rowsPerPageLabel": "Sorok száma egy oldalon",
"saveEdit": "Szerkesztés mentése",
"scrollTop": "Görgetés a tetejére",
"selectAll": "Összes elem kijelölve",
"selectLabel": "Válassza ki",
"selectRow": "Sor kijelölve",
"showFilterMenu": "Szűrő menü megjelenítése",
"slide": "Dia",
"slideNumber": "{slideNumber}",
"star": "1 csillag",
"stars": "{star} csillag",
"trueLabel": "Igaz",
"unselectAll": "Nincs elem kijelölve",
"unselectLabel": "Törölje a kijelölést",
"unselectRow": "Sor nincs kijelölve",
"zoomImage": "Kép nagyítása",
"zoomIn": "Nagyítás",
"zoomOut": "Kicsinyítés"
}
}
},
},
postcss: {
plugins: {
'postcss-import': {},
tailwindcss: {},
autoprefixer: {}
}
}
});

View File

@ -1,25 +1,51 @@
{
"name": "nuxt-app",
"name": "eurocars-rent",
"type": "module",
"version": "1.0.7",
"versionCode": 7,
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"generate": "nuxt generate",
"preview": "nuxt preview",
"postinstall": "nuxt prepare"
"postinstall": "nuxt prepare",
"cap": "cap",
"build:android": "nuxt generate && pnpm cap sync android && cd android && ./gradlew assembleDebug",
"build:android:release": "nuxt generate && pnpm cap sync android && cd android && ./gradlew bundleRelease",
"build:ios": "nuxt generate && pnpm cap sync ios"
},
"devDependencies": {
"@primevue/nuxt-module": "^4.2.5",
"autoprefixer": "^10.4.20",
"nuxt": "3.12.1",
"postcss": "^8.4.49",
"postcss-import": "^16.1.0"
"@capacitor/assets": "^3.0.5",
"@capacitor/cli": "^8.0.0",
"@iconify-json/ph": "^1.2.2",
"@nuxt/icon": "1.10.3",
"@pinia/nuxt": "0.9.0",
"@primevue/nuxt-module": "^4.3.9",
"@vite-pwa/nuxt": "0.10.6",
"autoprefixer": "^10.4.21",
"nuxt": "3.15.0",
"pinia": "^2.3.1",
"postcss": "^8.5.6",
"postcss-import": "^16.1.1",
"typescript": "^5.9.3"
},
"dependencies": {
"primevue": "^4.2.5",
"@capacitor/android": "^8.0.0",
"@capacitor/app": "^8.0.0",
"@capacitor/core": "^8.0.0",
"@capacitor/device": "^8.0.0",
"@capacitor/haptics": "^8.0.0",
"@capacitor/ios": "^8.0.0",
"@capacitor/preferences": "^8.0.0",
"@capacitor/splash-screen": "^8.0.0",
"@capacitor/status-bar": "^8.0.0",
"@pinia-plugin-persistedstate/nuxt": "^1.2.1",
"primeicons": "^7.0.0",
"primevue": "^4.3.9",
"tailwindcss": "^3.4.17",
"tailwindcss-primeui": "^0.3.4",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
}
"vue": "^3.5.21",
"vue-router": "^4.5.1"
},
"packageManager": "pnpm@9.14.4+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab"
}

View File

@ -1,12 +1,76 @@
<script setup>
</script>
<template>
<div class="flex items-center justify-center min-h-dvh p-10">
<div class="flex items-center justify-center p-10">
<section class="bg-white dark:bg-surface-900 p-10 rounded-xl flex flex-col gap-8 max-w-3xl ">
<h1 class="text-4xl text-black dark:text-white font-bold text-center">Nuxt + Tailwind CSS + PrimeVue
</h1>
</section>
</div>
</div>
</template>
<script setup>
const auth = useAuthStore()
const config = useMyConfigStore()
const rentals = computed(() => {
return auth.rentals
})
const states = computed(() => {
return config.states
})
function getStateName(id) {
if (id == '0') {
return 'Visszaigazolásra vár'
}
let match = states.value?.filter(x => { if (x.id == id) { return true } })
if (match?.length > 0) {
return match[0].name
}
}
function getYear(date) {
}
function getMont(date) {
}
import { Device } from '@capacitor/device';
const deviceInfo = await Device.getInfo();
const deviceId = await Device.getId();
</script>
<template>
<AppMenu />
<div v-if="!rentals">
<div class="p-3 text-center">
<div class="py-5">
<Icon name="ph:calendar-slash-thin" size="68" class="opacity-30" />
</div>
Jelenleg nincs foglalásod
</div>
</div>
<pre>{{deviceId}}</pre>
<pre>{{deviceInfo}}</pre>
<div v-for="rent in rentals" class="p-2">
<div class="p-card border-t border-t-4 border-primary">
<div class="ps-3">{{ getStateName(rent.status) }}</div>
<div v-if="rent.jaratszam" class="text-end text-xs pe-3"><span class="">járatszám:</span><b>{{
rent.jaratszam
}}</b></div>
<div class="flex items-baseline flex-row">
<div class="text-center p-2 w-full items-top">
<div class="text-xs">{{ rent.auto_felvetel_datum }}</div>
<div class="text-2xl">{{ rent.auto_felvetel_idopont }}</div>
<div class="text-xs">{{ rent.auto_felvetel_hely }}</div>
</div>
<div class="w-4"></div>
<div class="text-center p-2 w-full">
<div class="text-xs">{{ rent.auto_leadas_datum }}</div>
<div class="text-2xl">{{ rent.auto_leadas_idopont }}</div>
<div class="text-xs">{{ rent.auto_leadas_hely }}</div>
</div>
</div>
</div>
</div>
<div class="py-5 px-3 ">
<Button class="w-full" variant="success" icon="pi pi-plus" @click="$router.push({ path: '/rent' })">Új
foglalás</Button>
</div>
</template>

27
pages/login.vue Normal file
View File

@ -0,0 +1,27 @@
<template>
<div>
<div class="min-h-dvh px-5 pb-5">
<div class="flex flex-col gap-3 items-center justify-center text-center">
<div @click="$router.push({path:'/'})"
class="w-48 p-5 flex items-end">
<Logo class="w-full" :dark="isDark" />
</div>
<NuxtPage />
</div>
</div>
</div>
</template>
<script lang="ts" setup>
const isDark = ref(false)
onMounted(() => {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
isDark.value = mediaQuery.matches
mediaQuery.addEventListener('change', (e) => {
isDark.value = e.matches
})
})
</script>
<style></style>

124
pages/login/code.vue Normal file
View File

@ -0,0 +1,124 @@
<script lang="ts" setup>
const auth = useAuthStore()
const { setToken, loadToken, getToken } = useAuthToken()
const { apiFetch } = useApi()
const loginCode = ref()
const loginCodePrefix = ref()
const codeExpire = ref()
const account = ref()
const isLoading = ref(false)
const charcode = ref()
const errorMessage = ref()
const successMessage = ref()
const router = useRouter()
async function sendCode() {
isLoading.value = true
errorMessage.value = false
successMessage.value = false
const { data } = await apiFetch('/tokenRequest', {
method: "post",
body: {
account: account.value,
code: loginCode.value,
code_prefix: loginCodePrefix.value
}
})
if (data.value?.error) {
errorMessage.value = data.value?.message
}
if (data.value?.success) {
if (data.value?.message) {
successMessage.value = data.value?.message
}
if (data.value?.token) {
await setToken(data.value.token)
window.localStorage.removeItem('codePrefix')
window.localStorage.removeItem('codeExpire')
if (data.value?.user) {
auth.user = data.value.user
}
return navigateTo('/')
}
}
isLoading.value = false
}
function codeExpired() {
console.log('Code expired!')
loginCodePrefix.value = null
codeExpire.value = null
router.push({path:'/login'})
}
function changeCode() {
if (loginCode.value.length === 4) {
sendCode()
}
}
onMounted(async () => {
// Ha már be van jelentkezve, irányítsuk a főoldalra
await loadToken()
const token = getToken()
if (token) {
return navigateTo('/')
}
loginCodePrefix.value = window.localStorage.getItem('codePrefix')
codeExpire.value = window.localStorage.getItem('codeExpire')
account.value = window.localStorage.getItem('account')
window.document.addEventListener('keydown', function(e){
console.log(e)
charcode.value = e.key
if(e.key === 'Backspace' && loginCode.value.length > 0){
loginCode.value = loginCode.value.substr(0,loginCode.value.length-1)
}
})
})
</script>
<template>
<div>
<Message class="w-full" severity="error" v-if="errorMessage">{{ errorMessage }}</Message>
<Message class="w-full" severity="success" v-if="successMessage">{{ successMessage }}</Message>
<div class="p-2">
Add meg a kódot amit a(z) <b>{{ account }}</b> e-mail címre küldött ki rendszerünk.
</div>
<Card>
<template #content>
<div class="flex flex-wrap justify-center gap-1 items-center p-2 relative">
<CardLoading v-if="isLoading" />
<InputOtp v-model="loginCodePrefix" :length="2" style="gap: 1; opacity:1" in disabled size="small">
</InputOtp>
<div><i class="pi pi-minus"></i></div>
<InputOtp v-model="loginCode" :length="4" style="gap: 1" size="small" @change="changeCode($event)" integer-only></InputOtp>
</div>
</template>
</Card>
<div class="p-2">
A kód még <b>
<Countdown v-if="codeExpire" :expired="codeExpire" @end="codeExpired()" />
</b> percig érvényes. Lejárat után új kódot kell igényelned.
</div>
<Alert>
{{ errorMessage }}
</Alert>
<Button @click="sendCode()" class="w-full" icon="pi pi-check-circles">Kód küldése</Button>
<Button @click="$router.push({path:'/login'})" variant="link" class="w-full mt-3" icon="pi pi-check-circles">Új kód kérése</Button>
</div>
</template>
<style>
.p-disabled, .p-component:disabled
{
opacity: 0.9;
}</style>

86
pages/login/index.vue Normal file
View File

@ -0,0 +1,86 @@
<template>
<div>
<Message class="w-full" severity="error" v-if="errorMessage">{{ errorMessage }}</Message>
<Message class="w-full" severity="success" v-if="successMessage">{{ successMessage }}</Message>
<h1 class="text-2xl py-3">Kérjük, add meg az e-mail címedet</h1>
<div>Ha már korábban volt foglalásod vagy regisztrációd akkor azt az e-mail címet add meg.</div>
<Card class="w-full max-w-sm m-auto mt-3">
<template #content>
<div class="flex flex-col gap-5 items-center p-2 relative w-full">
<CardLoading v-if="isLoading" />
<FloatLabel variant="on" class="w-full">
<InputText id="email_label" v-model="account" autocomplete="off" class="w-full" />
<label for="email_label">E-mail cím</label>
</FloatLabel>
<div class="text-xs">Az e-mail cím megadásával elfogadod a felhasználási feltételeinket. Az
adatvédelemről az Adatvédelmi nyilatkozat linken olvashatsz.</div>
<Button @click="sendAccount()" class="w-full" icon="pi pi-check-circles">Megadom az e-mail
címem</Button>
</div>
</template>
</Card>
<div class="text-center text-xs mt-5" v-if="configStore?.config">
<NuxtLink :to="'/page/' + configStore?.config?.adatvedelem_id">Adatvédelmi nyilatkozat</NuxtLink>
</div>
</div>
</template>
<script lang="ts" setup>
const token = useAuthToken()
const configStore = useMyConfigStore()
const { apiFetch } = useApi()
const errorMessage = ref()
const successMessage = ref()
const isLoading = ref()
const account = ref()
const router = useRouter()
async function sendAccount() {
errorMessage.value = false
successMessage.value = false
isLoading.value = true
const { data } = await apiFetch('/authRequest', {
method: "post",
body: {
account: account.value
}
})
if (data.value?.error) {
errorMessage.value = data.value.message
}
if (data.value?.success) {
window.localStorage.setItem('codePrefix', data.value.codePrefix)
window.localStorage.setItem('codeExpire', data.value.codeExpire)
window.localStorage.setItem('account', data.value.account)
if (data.value?.message) {
successMessage.value = data.value.message
}
router.push({ path: '/login/code', force: true })
}
isLoading.value = false
}
onMounted(async () => {
// Ha már be van jelentkezve, irányítsuk a főoldalra
const { loadToken, getToken } = useAuthToken()
await loadToken()
const token = getToken()
if (token) {
return navigateTo('/')
}
account.value = window.localStorage.getItem('account')
})
</script>
<style></style>

38
pages/page/[id].vue Normal file
View File

@ -0,0 +1,38 @@
<template>
<div>
<AppMenu />
<div class="flex items-center border-b mb-3 border-primary p-3">
<h1 class="text-center w-full" v-if="Title">{{ Title }}</h1>
<Skeleton width="85%" v-if="isLoading"></Skeleton>
</div>
<div class="p-3">
<div v-if="isLoading">
<Skeleton></Skeleton>
<Skeleton width="85%" class="my-2"></Skeleton>
<Skeleton width="75%"></Skeleton>
</div>
<div v-html="Content"></div>
</div>
</div>
</template>
<script lang="ts" setup>
const Title = ref()
const Content = ref()
const route = useRoute()
const isLoading = ref(true)
const { apiFetch } = useApi()
onMounted(async()=>{
const {data} = await apiFetch('/getPage', { query:{id:route.params.id}})
if(data.value?.success){
Title.value = data.value?.page.post_title
Content.value = data.value?.page.post_content
}
isLoading.value = false
})
</script>
<style>
</style>

168
pages/profile/index.vue Normal file
View File

@ -0,0 +1,168 @@
<template>
<div>
<AppMenu />
<div class="flex justify-center items-center border-b mb-3 border-primary">
<div class="py-3 text-center">Adataim</div>
</div>
<div class="p-3 space-y-3">
<PageLoading v-if="isLoading" />
<div v-if="!hasAllRequiredData" class="p-3 bg-yellow-100 dark:bg-yellow-900 border border-yellow-400 dark:border-yellow-600 rounded-lg text-yellow-800 dark:text-yellow-200 text-sm">
<i class="pi pi-exclamation-triangle mr-2"></i>
Kérjük, töltsd ki az összes kötelező adatot a folytatáshoz!
</div>
<FloatLabel variant="on">
<InputText id="name" v-model="user.nev" class="w-full" :invalid="!user.nev" />
<label for="name">Név</label>
</FloatLabel>
<FloatLabel variant="on">
<InputText id="email" v-model="user.email" class="w-full" :invalid="!user.email" />
<label for="email">E-mail</label>
</FloatLabel>
<FloatLabel variant="on">
<InputText id="telefon" v-model="user.telefon" class="w-full" :invalid="!user.telefon" />
<label for="telefon">Telefon</label>
</FloatLabel>
<FloatLabel variant="on">
<InputText id="anyja_neve" v-model="user.anyja_neve" class="w-full" :invalid="!user.anyja_neve" />
<label for="anyja_neve">Anyja neve</label>
</FloatLabel>
<FloatLabel variant="on">
<InputText id="szuletesi_hely" v-model="user.szuletesi_hely" class="w-full" :invalid="!user.szuletesi_hely" />
<label for="szuletesi_hely">Születési hely</label>
</FloatLabel>
<div class="p-floatlabel p-floatlabel-on p-inputtext p-component" :class="{ 'p-invalid': !user.szuletesi_ido }"
style="height: 47px;">
<Birthday v-model="user.szuletesi_ido" />
<label for=""
style="transform: matrix(1, 0, 0, 1, 0, -30); font-size: 13.5px; font-weight: normal;padding:0px 2px;"
class="bg-inherit" :class="{ 'p-invalid': !user.szuletesi_ido }">Születési idő</label>
</div>
<FloatLabel variant="on">
<InputText id="nemzetiseg" v-model="user.nemzetiseg" class="w-full" :invalid="!user.nemzetiseg" />
<label for="nemzetiseg">Állampolgárság</label>
</FloatLabel>
<FloatLabel variant="on">
<InputText id="szigszam" v-model="user.szigszam" class="w-full" :invalid="!user.szigszam" />
<label for="szigszam">Személyi igazolvány / Útlevél száma</label>
</FloatLabel>
<FloatLabel variant="on">
<InputText id="jogositvany_szama" v-model="user.jogositvany_szama" class="w-full"
:invalid="!user.jogositvany_szama" />
<label for="jogositvany_szama">Jogosítvány száma</label>
</FloatLabel>
<FloatLabel variant="on">
<InputText id="lakcim" v-model="user.lakcim" class="w-full" :invalid="!user.lakcim" />
<label for="lakcim">Lakcím</label>
</FloatLabel>
<div class="flex items-center gap-2">
<ToggleSwitch v-model="sameAddress" />
<span class="text-sm">Tartózkodási cím megegyezik a lakcímmel</span>
</div>
<FloatLabel v-if="!sameAddress" variant="on">
<InputText id="tartozkodasicim" v-model="user.tartozkodasicim" class="w-full"
:invalid="!user.tartozkodasicim" />
<label for="tartozkodasicim">Tartózkodási cím</label>
</FloatLabel>
<div>
Lakcím:
</div>
<UserAddress v-model="lakcimData" />
<Dialog v-model:visible="showDialog" modal :header="dialogType === 'success' ? 'Sikeres' : 'Hiba'" :style="{ width: '20rem' }">
<div class="flex items-center gap-3">
<i :class="dialogType === 'success' ? 'pi pi-check-circle text-green-500' : 'pi pi-times-circle text-red-500'" style="font-size: 2rem"></i>
<span>{{ dialogMessage }}</span>
</div>
<div class="border-b border border-red-500 mt-3 mb-2" v-if="dialogErrors"></div>
<div v-for="err in dialogErrors" class="text-sm">
&bull; {{ err }}
</div>
<template #footer>
<Button label="Rendben" @click="showDialog = false" class="w-full" />
</template>
</Dialog>
<div class="">
<Button @click="save()" class="w-full min-w-20" icon="pi pi-save">Adatok mentése</Button>
</div>
<div class="pt-6">
<Button @click="logout()" severity="danger" variant="link" class="w-full" icon="pi pi-sign-out">Kijelentkezés</Button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
const isLoading = ref(false)
const sameAddress = ref(true)
const authStore = useAuthStore()
const { user, rent } = storeToRefs(authStore)
const { loadToken } = useAuthToken()
const { apiRequest } = useApi()
const showDialog = ref(false)
const dialogType = ref<'success' | 'error'>('success')
const dialogMessage = ref('')
const dialogErrors = ref()
const lakcimData = ref()
// Kötelező mezők listája
const requiredFields = [
'nev',
'email',
'telefon',
'anyja_neve',
'szuletesi_hely',
'szuletesi_ido',
'nemzetiseg',
'szigszam',
'jogositvany_szama',
'lakcim'
] as const
// Ellenőrzi, hogy minden kötelező mező ki van-e töltve
const hasAllRequiredData = computed(() => {
if (!user.value) return false
const userData = user.value as unknown as Record<string, any>
return requiredFields.every(field => {
const value = userData[field]
return value && (typeof value !== 'string' || value.trim() !== '')
})
})
async function save() {
isLoading.value = true
const token = await loadToken()
console.log(token)
dialogErrors.value = null
const data = await apiRequest<{ success: boolean; message: string }>('/update_profile',
{
headers: {
'auth-key': token || ''
},
method: 'POST',
body: {
sameAddress: sameAddress.value,
user: user.value
}
}
)
isLoading.value = false
if (data.success) {
dialogType.value = 'success'
dialogMessage.value = data.message
} else {
dialogType.value = 'error'
dialogMessage.value = data.message || 'Hiba történt'
dialogErrors.value = data?.errors
}
showDialog.value = true
}
async function logout() {
await authStore.logout()
}
</script>
<style></style>

70
pages/rent.vue Normal file
View File

@ -0,0 +1,70 @@
<template>
<div>
<AppMenu />
<!-- <div class="flex justify-between items-center h-16">
<Button @click="$router.back()" link icon="pi pi-arrow-left" v-if="$route.meta?.rentStep < 8"></Button>
<div class="px-3">{{ $route?.meta?.title }}</div>
</div> -->
<div class="">
<RentStep v-if="$route.meta?.rentStep < 8" />
<!-- <Stepper value="1" linear>
<StepList>
<Step value="1">Autófelvétel</Step>
<Step value="2"></Step>
<Step value="3"></Step>
</StepList>
</Stepper> -->
<NuxtPage />
<!-- <pre>{{ rent }}</pre> -->
</div>
</div>
</template>
<script lang="ts" setup>
const { rent } = useAuthStore()
const prevPage = ref()
definePageMeta({
pageTransition: {
name: 'slide-right',
mode: 'out-in'
},
middleware(to, from) {
if (to.meta.pageTransition && typeof to.meta.pageTransition !== 'boolean')
console.log(to.meta)
to.meta.pageTransition.name = +to.meta.rentStep! > +from.meta.rentStep! ? 'slide-left' : 'slide-right'
prevPage.value = from.fullPath
}
})
</script>
<style>
.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active {
transition: all 0.2s;
}
.slide-left-enter-from {
opacity: 0;
transform: translate(50px, 0);
}
.slide-left-leave-to {
opacity: 0;
transform: translate(-50px, 0);
}
.slide-right-enter-from {
opacity: 0;
transform: translate(-50px, 0);
}
.slide-right-leave-to {
opacity: 0;
transform: translate(50px, 0);
}
</style>

47
pages/rent/category.vue Normal file
View File

@ -0,0 +1,47 @@
<template>
<div>
<div class="text-center">Kategória</div>
<div class="flex flex-col gap-3 p-3">
<Card v-for="categori in categories" :pt="{ root: '' }" @click="next(categori)">
<template #content>
<div class="flex">
<div class="flex justify-center items-center text-3xl font-bold" style="width: 56px; font-size: 32px;">{{
categori.shortname }}</div>
<div>
<div class="text-sm">{{ categori.name }}</div>
<div class="text-primary-500">{{ HUFormat.format(categori.price) }} / nap</div>
</div>
</div>
</template>
</Card>
</div>
</div>
</template>
<script lang="ts" setup>
const { rent } = storeToRefs(useAuthStore())
definePageMeta({
rentStep: 6,
title: 'Válassz egy kategóriát'
})
const categoriestStore = useCategoriesStore()
const categories: CategoryType[] = computed(() => {
return categoriestStore.categories
})
let HUFormat = new Intl.NumberFormat('hu-HU', {
style: 'currency',
currency: 'HUF',
maximumFractionDigits: 0
});
function next(category) {
rent.value.category_id = category.category_id
rent.value.valasztott_auto = category.shortname + ' ' + category.name
navigateTo('/rent/preview')
}
</script>
<style></style>

83
pages/rent/date-to.vue Normal file
View File

@ -0,0 +1,83 @@
<template>
<div>
<div class="text-center">Autóbérlés vége</div>
<div class="flex flex-col p-3">
<DatePicker inline :min-date="minDate" v-model="selectedDate" />
</div>
<div class="flex flex-col p-3">
Időpont
<Dropdown :options="timeList" v-model="rent.auto_leadas_idopont" />
</div>
<div class="p-3">
<Button @click="next()" class="max-sm:w-full min-w-20"
v-if="rent.auto_leadas_datum && rent.auto_leadas_idopont">Tovább</Button>
</div>
</div>
</template>
<script lang="ts" setup>
const { rent } = storeToRefs(useAuthStore())
definePageMeta({
rentStep: 3,
title: 'Autóbérlés vége'
})
// Helyi Date objektum a DatePicker-hez
const selectedDate = ref<Date | null>(rent.value.auto_leadas_datum ? new Date(rent.value.auto_leadas_datum) : null)
// Min dátum a felvételi dátumból
const minDate = computed(() => {
return rent.value.auto_felvetel_datum ? new Date(rent.value.auto_felvetel_datum) : new Date()
})
// Ha változik a kiválasztott dátum, szöveggé alakítjuk (YYYY-MM-DD)
watch(selectedDate, (newDate) => {
if (newDate) {
const year = newDate.getFullYear()
const month = String(newDate.getMonth() + 1).padStart(2, '0')
const day = String(newDate.getDate()).padStart(2, '0')
rent.value.auto_leadas_datum = `${year}-${month}-${day}`
} else {
rent.value.auto_leadas_datum = null
}
})
function next() {
navigateTo('/rent/place-to')
}
const rentDays = computed(() => {
// Dátum stringek összehasonlítása
const kezdoDatumObj = new Date(rent.value.auto_felvetel_datum);
const vegDatumObj = new Date(rent.value.auto_leadas_datum);
// A két dátum közötti különbség millimásodpercben
const kulonbsegMs = vegDatumObj.getTime() - kezdoDatumObj.getTime();
// Átváltás napokba (egy nap 86400000 millimásodperc)
const napok = Math.floor(kulonbsegMs / 86400000);
return napok + 1;
})
const timeList = computed(() => {
let a = []
for (let i = 0; i < 24; i++) {
if (rent.value.auto_leadas_datum == rent.value.auto_felvetel_datum) {
if (rent.value.auto_felvetel_idopont < i + ':00') {
a.push(i + ':00')
}
if (rent.value.auto_felvetel_idopont < i + ':30') {
a.push(i + ':30')
}
} else {
a.push(i + ':00')
a.push(i + ':30')
}
}
return a
})
</script>
<style></style>

86
pages/rent/extra.vue Normal file
View File

@ -0,0 +1,86 @@
<template>
<div class="p-3">
<div>
<div><span class="text-red-500">*</span> Autó használata:</div>
<div class="flex flex-col gap-4 p-3">
<div class="flex items-center gap-2">
<RadioButton v-model="rent.hasznalat" inputId="hasznalat-belfold" name="hasznalat" value="belfold" />
<label for="hasznalat-belfold" class="text-sm">Belföld</label>
</div>
<div class="flex items-center gap-2">
<RadioButton v-model="rent.hasznalat" inputId="hasznalat-kulfold" name="hasznalat" value="kulfold" />
<label for="hasznalat-kulfold" class="text-sm">Belföld és külföld</label>
</div>
</div>
</div>
<Divider />
<div class="flex items-center gap-2 text-small">
<ToggleSwitch name="matrica" v-model="rent.palyamatrica" input-id="palyamatrica" />
<label for="palyamatrica">Magyar autópálya matrica</label>
</div>
<Divider />
<div>
<div>Opcionálisan bérelhető tartozékok:</div>
<div class="flex flex-col gap-4 p-3">
<div class="flex items-center gap-2">
<Checkbox v-model="rent.tartozekok" inputId="tartozekok-snowchain" name="tartozekok[]" value="snowchain" />
<label for="tartozekok-snowchain" class="text-sm">Hólánc</label>
</div>
<div class="flex items-center gap-2">
<Checkbox v-model="rent.tartozekok" inputId="tartozekok-childsheat" name="tartozekok[]" value="childsheat" />
<label for="tartozekok-childsheat" class="text-sm">Gyerekülés</label>
</div>
</div>
</div>
<Divider />
<div>
<div><span class="text-red-500">*</span> Fizetési mód:</div>
<div class="flex flex-col gap-4 p-3">
<div class="flex items-center gap-2">
<RadioButton v-model="rent.fizetesi_mod" inputId="fizetesi_mod-1" name="payment" value="1" />
<label for="fizetesi_mod-1" class="text-sm">Készpénzzel a helyszínen</label>
</div>
<div class="flex items-center gap-2">
<RadioButton v-model="rent.fizetesi_mod" inputId="fizetesi_mod-2" name="payment" value="2" />
<label for="fizetesi_mod-2" class="text-sm">Banki előre utalás</label>
</div>
<div class="flex items-center gap-2">
<RadioButton v-model="rent.fizetesi_mod" inputId="fizetesi_mod-3" name="payment" value="3" />
<label for="fizetesi_mod-3" class="text-sm">Bankkártyával a helyszínen</label>
</div>
</div>
</div>
<Divider />
<div>
<div>Üzenet:</div>
<Textarea rows="4" class="w-full text-sm" placeholder="Ha szeretnél nekünk üzenni az autóbérléssel kapcsolatosan, akkor itt megteheted."></Textarea>
</div>
<div class="py-3">
<Button @click="next()" class="w-full" :disabled="isValid">Tovább</Button>
</div>
</div>
</template>
<script lang="ts" setup>
const { rent } = storeToRefs(useAuthStore())
definePageMeta({
rentStep:5,
title: ''
})
const hasznalatOptions = ref([{ value: 'belfold', label: 'Belföld' }, { value: 'kulfold', label: 'Belföld és külföld' }])
function next() {
navigateTo('/rent/category')
}
const isValid = computed(()=>{
if(!rent.value?.hasznalat) return true
if(!rent.value?.fizetesi_mod) return true
return false
})
</script>
<style></style>

55
pages/rent/index.vue Normal file
View File

@ -0,0 +1,55 @@
<template>
<div>
<div class="text-center">Autóbérlés kezdete</div>
<div class="flex flex-col p-3">
<DatePicker inline :min-date="(new Date())" v-model="selectedDate"/>
</div>
<div class="flex flex-col p-3">
Időpont
<Dropdown :options="timeList" v-model="rent.auto_felvetel_idopont" />
</div>
<div class="p-3">
<Button @click="next()" class="max-sm:w-full min-w-20" v-if="rent.auto_felvetel_datum && rent.auto_felvetel_idopont">Tovább</Button>
</div>
</div>
</template>
<script lang="ts" setup>
const {rent} = storeToRefs(useAuthStore())
definePageMeta({
rentStep: 1,
title:'Autóbérlés kezdete'
})
// Helyi Date objektum a DatePicker-hez
const selectedDate = ref<Date | null>(rent.value.auto_felvetel_datum ? new Date(rent.value.auto_felvetel_datum) : null)
// Ha változik a kiválasztott dátum, szöveggé alakítjuk (YYYY-MM-DD)
watch(selectedDate, (newDate) => {
if (newDate) {
const year = newDate.getFullYear()
const month = String(newDate.getMonth() + 1).padStart(2, '0')
const day = String(newDate.getDate()).padStart(2, '0')
rent.value.auto_felvetel_datum = `${year}-${month}-${day}`
} else {
rent.value.auto_felvetel_datum = null
}
})
function next() {
navigateTo('/rent/place-from')
}
const timeList = computed(()=>{
let a = []
for(let i=0; i<24; i++){
a.push(i+':00')
a.push(i+':30')
}
return a
})
</script>
<style></style>

31
pages/rent/jaratszam.vue Normal file
View File

@ -0,0 +1,31 @@
<template>
<div class="flex flex-col p-3 gap-3">
Járatszám
<InputText v-model="rent.jaratszam" :style="{'text-transform': 'uppercase'}" />
<div class="text-center">
<Button class="w-full mb-5" @click="next()">Tovább</Button>
<NuxtLink @click="next(1)">Nem adok meg járatszámot</NuxtLink>
</div>
</div>
</template>
<script lang="ts" setup>
const {rent} = useAuthStore()
const router = useRouter()
definePageMeta({
rentStep: 2.5,
title:'Járatszám'
})
function next(clear: any = false){
if(clear){
rent.jaratszam = null
}
router.push({path:'/rent/date-to'})
}
</script>
<style>
</style>

63
pages/rent/place-from.vue Normal file
View File

@ -0,0 +1,63 @@
<template>
<div>
<div class="text-center">Autófelvétel helye</div>
<div class="flex flex-col gap-3 p-3">
<Card v-for="place in places" :pt="{ root: (rent.auto_felvetel_hely == place) ? 'bg-primary-500 text-white mb-3' : 'mb-3' }">
<template #content>
<div class="flex gap-3" @click="next(place)">
<div class="flex justify-center items-center text-3xl font-bold" style="width: 56px; font-size: 32px;">
<template v-if="place.icon == 'airplane'">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 256 256">
<path fill="currentColor"
d="M256 216a8 8 0 0 1-8 8H104a8 8 0 0 1 0-16h144a8 8 0 0 1 8 8m-26.16-24.3L53.21 142.24A40.12 40.12 0 0 1 24 103.72V48a16 16 0 0 1 21.06-15.18l5.47 1.82a8 8 0 0 1 5 4.87l10.6 29.37L96 77.39V48a16 16 0 0 1 21.06-15.18l5.47 1.82a8 8 0 0 1 4.85 4.5l22.5 53.63l60.84 17A40.13 40.13 0 0 1 240 148.32V184a8 8 0 0 1-10.16 7.7M224 148.32a24.09 24.09 0 0 0-17.58-23.13l-64.57-18a8 8 0 0 1-5.23-4.61L114 48.67l-2-.67v40a8 8 0 0 1-10.19 7.7l-44-12.54a8 8 0 0 1-5.33-5L41.79 48.59L40 48v55.72a24.09 24.09 0 0 0 17.53 23.12L224 173.45Z" />
</svg>
</template>
<template v-if="place.icon == 'office'">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 256 256"><path fill="currentColor" d="M248 208h-16V96a8 8 0 0 0 0-16h-48V48a8 8 0 0 0 0-16H40a8 8 0 0 0 0 16v160H24a8 8 0 0 0 0 16h224a8 8 0 0 0 0-16M216 96v112h-32V96ZM56 48h112v160h-24v-48a8 8 0 0 0-8-8H88a8 8 0 0 0-8 8v48H56Zm72 160H96v-40h32ZM72 80a8 8 0 0 1 8-8h16a8 8 0 0 1 0 16H80a8 8 0 0 1-8-8m48 0a8 8 0 0 1 8-8h16a8 8 0 0 1 0 16h-16a8 8 0 0 1-8-8m-48 40a8 8 0 0 1 8-8h16a8 8 0 0 1 0 16H80a8 8 0 0 1-8-8m48 0a8 8 0 0 1 8-8h16a8 8 0 0 1 0 16h-16a8 8 0 0 1-8-8"/></svg>
</template>
</div>
<div class="w-full">
<div class="text-sm"><b>{{ place.name }}</b></div>
<div class="text-sm">{{ place.address }}</div>
</div>
</div>
</template>
</Card>
</div>
</div>
</template>
<script lang="ts" setup>
const {rent} = storeToRefs(useAuthStore())
definePageMeta({
rentStep: 2,
title:'Autófelvétel helye'
})
const placeStore = useMyPlacesStore()
const places: PlaceType[] = computed(() => {
return placeStore.places
})
let HUFormat = new Intl.NumberFormat('hu-HU', {
style: 'currency',
currency: 'HUF',
maximumFractionDigits: 0
});
function next(val) {
rent.value.auto_felvetel_hely=val
if(val.id == '3'){
navigateTo('/rent/jaratszam')
}else{
navigateTo('/rent/date-to')
}
}
function prev() {
navigateTo('/rent')
}
</script>
<style></style>

56
pages/rent/place-to.vue Normal file
View File

@ -0,0 +1,56 @@
<template>
<div>
<div class="text-center">Autóleadás helye</div>
<div class="flex flex-col gap-3 p-3">
<Card v-for="place in places"
:pt="{ root: (rent.auto_leadas_hely == place) ? 'bg-primary-500 text-white mb-3' : 'mb-3' }">
<template #content>
<div class="flex gap-3" @click="next(place)">
<div class="flex justify-center items-center text-3xl font-bold" style="width: 56px; font-size: 32px;">
<template v-if="place.icon == 'airplane'">
<Icon name="ph:airplane-takeoff" size="48" />
</template>
<template v-if="place.icon == 'office'">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 256 256">
<path fill="currentColor"
d="M248 208h-16V96a8 8 0 0 0 0-16h-48V48a8 8 0 0 0 0-16H40a8 8 0 0 0 0 16v160H24a8 8 0 0 0 0 16h224a8 8 0 0 0 0-16M216 96v112h-32V96ZM56 48h112v160h-24v-48a8 8 0 0 0-8-8H88a8 8 0 0 0-8 8v48H56Zm72 160H96v-40h32ZM72 80a8 8 0 0 1 8-8h16a8 8 0 0 1 0 16H80a8 8 0 0 1-8-8m48 0a8 8 0 0 1 8-8h16a8 8 0 0 1 0 16h-16a8 8 0 0 1-8-8m-48 40a8 8 0 0 1 8-8h16a8 8 0 0 1 0 16H80a8 8 0 0 1-8-8m48 0a8 8 0 0 1 8-8h16a8 8 0 0 1 0 16h-16a8 8 0 0 1-8-8" />
</svg>
</template>
</div>
<div class="w-full">
<div class="text-sm"><b>{{ place.name }}</b></div>
<div class="text-sm">{{ place.address }}</div>
</div>
</div>
</template>
</Card>
</div>
</div>
</template>
<script lang="ts" setup>
const { rent } = storeToRefs(useAuthStore())
definePageMeta({
rentStep: 4,
title: 'Autóleadás helye'
})
const placeStore = useMyPlacesStore()
const places: PlaceType[] = computed(() => {
return placeStore.places
})
let HUFormat = new Intl.NumberFormat('hu-HU', {
style: 'currency',
currency: 'HUF',
maximumFractionDigits: 0
});
function next(val) {
rent.value.auto_leadas_hely = val
navigateTo('/rent/extra')
}
</script>
<style></style>

119
pages/rent/preview.vue Normal file
View File

@ -0,0 +1,119 @@
<template>
<div class="p-3">
<div class="p-card border-t border-t-4 border-primary p-4">
<div class="flex justify-between"><b>Név: </b>{{ user.nev }}</div>
<div class="flex justify-between"><b>E-mail: </b>{{ user.email }}</div>
<div class="flex justify-between"><b>Telefon: </b>{{ user.telefon }}</div>
<div class="flex justify-between"><b>Anyja neve: </b>{{ user.anyja_neve }}</div>
<div class="flex justify-between"><b>Születési hely: </b>{{ user.szuletesi_hely }}</div>
<div class="flex justify-between"><b>Születési idő: </b>{{ user.szuletesi_ido }}</div>
<div class="flex justify-between"><b>Állampolgárság: </b>{{ user.nemzetiseg }}</div>
<div class="text-sm mt-3"><b>Személyi igazolvány / Útlevél száma: </b><br>{{ user.szigszam }}</div>
<div class="text-sm"><b>Jogosítvány száma: </b><br>{{ user.jogositvany_szama }}</div>
<div class="text-sm"><b>Lakcím: </b><br>{{ user.lakcim }}</div>
<div class="text-sm"><b>Tartózkodási cím: </b><br>{{ user.tartozkodasicim }}</div>
<Message v-if="missingFields.length > 0" class="mt-2" severity="error">
<div>Hiányzó adatok:</div>
<ul class="list-disc list-inside">
<li v-for="field in missingFields" :key="field.key">{{ field.label }}</li>
</ul>
</Message>
<Message v-else class="mt-2 text-center" severity="warn">Amennyiben adataidban változás történt, módosítsd a <span class="text-nowrap"><i
class="pi pi-user mx-1"></i> profilodban</span>.</Message>
<div class="text-center">
<Button variant="link" @click="$router.push({ path: '/profile' })">Adatok módosítása</Button>
</div>
</div>
<div class="space-y-4 mt-4">
<div class="p-card border-t border-t-4 border-primary">
<div v-if="rent.jaratszam" class="text-end text-xs pe-3"><span class="">járatszám:</span><b>{{
rent.jaratszam
}}</b></div>
<div class="flex items-baseline flex-row">
<div class="text-center p-2 w-full items-top">
<div class="text-xs">{{ rent.auto_felvetel_datum }}</div>
<div class="text-2xl">{{ rent.auto_felvetel_idopont }}</div>
<div class="text-xs">{{ rent.auto_felvetel_hely?.name }}</div>
</div>
<div class="w-4"></div>
<div class="text-center p-2 w-full">
<div class="text-xs">{{ rent.auto_leadas_datum }}</div>
<div class="text-2xl">{{ rent.auto_leadas_idopont }}</div>
<div class="text-xs">{{ rent.auto_leadas_hely?.name }}</div>
</div>
</div>
</div>
<div class="flex items-start gap-1" v-for="t in config?.rent.confirms">
<Checkbox v-model="confirms" :inputId="`confirm${t.id}`" name="confirms[]" :value="t.id" />
<label :for="`confirm${t.id}`" class="text-sm">{{ t.label }}</label>
</div>
</div>
<div class="py-5">
<Button @click="sendRent()" class="w-full" :disabled="isValid">Foglalás
elküldése</Button>
</div>
</div>
</template>
<script lang="ts" setup>
const { rent, user } = storeToRefs(useAuthStore())
const { config } = storeToRefs(useMyConfigStore())
const { apiRequest } = useApi()
const confirms = ref([])
const requiredFields = [
{ key: 'nev', label: 'Név' },
{ key: 'email', label: 'E-mail' },
{ key: 'telefon', label: 'Telefon' },
{ key: 'anyja_neve', label: 'Anyja neve' },
{ key: 'szuletesi_hely', label: 'Születési hely' },
{ key: 'szuletesi_ido', label: 'Születési idő' },
{ key: 'nemzetiseg', label: 'Állampolgárság' },
{ key: 'szigszam', label: 'Személyi igazolvány / Útlevél száma' },
{ key: 'jogositvany_szama', label: 'Jogosítvány száma' },
{ key: 'lakcim', label: 'Lakcím' },
{ key: 'tartozkodasicim', label: 'Tartózkodási cím' }
]
const missingFields = computed(() => {
return requiredFields.filter(field => !user.value?.[field.key])
})
const isUserDataValid = computed(() => {
return missingFields.value.length === 0
})
definePageMeta({
rentStep: 7,
title: 'Foglalás áttekintése'
})
const isValid = computed(() => {
if (!isUserDataValid.value) return true
if (config.value?.rent.confirms.length > confirms.value?.length) return true
return false
})
async function sendRent(){
console.log(rent.value)
const data = await apiRequest('/rent', {
method: 'POST',
body:{
user:user.value,
rent:rent.value
}
})
if(data?.success){
}
if(data?.error){
}
}
</script>
<style></style>

17
pages/rent/profile.vue Normal file
View File

@ -0,0 +1,17 @@
<template>
<div>
</div>
</template>
<script lang="ts" setup>
definePageMeta({
rentStep: 6,
title:''
})
</script>
<style>
</style>

27
pages/rent/thanks.vue Normal file
View File

@ -0,0 +1,27 @@
<template>
<div class="p-3">
<div class="bg-gray-500 bg-opacity-20 rounded-full w-24 h-24 flex items-center justify-center mx-auto">
<Icon name="ph:calendar-check" size="72" class="text-green-600 dark:text-green-400" />
</div>
<div class="text-center font-bold text-green-600 dark:text-green-400 my-3"
v-html="config?.rent.thanks_message.title"></div>
<div class="text-center text-sm" v-html="config?.rent.thanks_message.content"></div>
<Button icon="i-ph-check-circle" class="my-3 w-full" @click="$router.push({ path: '/' })">Rendben</Button>
</div>
</template>
<script lang="ts" setup>
const { rent } = storeToRefs(useAuthStore())
const { config } = storeToRefs(useMyConfigStore())
definePageMeta({
rentStep: 8,
title: ''
})
onMounted(() => {
// rent.value = null
})
</script>
<style></style>

125
plugins/capacitor.client.ts Normal file
View File

@ -0,0 +1,125 @@
import { App } from '@capacitor/app'
import { StatusBar, Style } from '@capacitor/status-bar'
import { SplashScreen } from '@capacitor/splash-screen'
import { Haptics, ImpactStyle } from '@capacitor/haptics'
import { Capacitor } from '@capacitor/core'
export default defineNuxtPlugin(async (nuxtApp) => {
const siteData = ref()
const categoriesStore = useCategoriesStore()
const placeStore = useMyPlacesStore()
const authStore = useAuthStore()
const configStore = useMyConfigStore()
const { loadToken, getToken } = useAuthToken()
const { apiFetch } = useApi()
const token = await loadToken()
console.log(token)
const { data } = await apiFetch('/init',
{
headers: {
'auth-key': token || ''
}
}
)
if (data.value?.user) {
authStore.user = data.value.user
}
if (data.value?.config) {
configStore.config = data.value.config
}
if (data.value?.states) {
configStore.states = data.value.states
}
if (data.value?.categories) {
categoriesStore.categories = data.value.categories
placeStore.places = data.value.places
}
if (data.value?.countries) {
configStore.countries = data.value.countries
}
// Csak natív platformon fut
if (!Capacitor.isNativePlatform()) {
return
}
const router = useRouter()
// Android hardware back button kezelése
App.addListener('backButton', async ({ canGoBack }) => {
// Ha van history, navigáljunk vissza
if (router.currentRoute.value.path !== '/' && window.history.length > 1) {
router.back()
} else {
// Ha a főoldalon vagyunk, minimalizáljuk az appot
App.minimizeApp()
}
})
// Status bar beállítása dark/light mode alapján
const setupStatusBar = async (isDark: boolean) => {
try {
if (Capacitor.getPlatform() === 'android') {
await StatusBar.setBackgroundColor({ color: '#262626' }) // surface-950
await StatusBar.setStyle({ style: Style.Dark }) // világos ikonok
}
} catch (e) {
console.warn('StatusBar setup error:', e)
}
}
// Splash screen elrejtése amikor az app betöltődött
const hideSplash = async () => {
try {
await SplashScreen.hide({
fadeOutDuration: 300
})
} catch (e) {
console.warn('SplashScreen hide error:', e)
}
}
// Dark mode figyelése
const darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)')
// Dark mode változás figyelése
darkModeQuery.addEventListener('change', (e) => {
setupStatusBar(e.matches)
})
// App mounted hook
nuxtApp.hooks.hook('app:mounted', async () => {
// Kezdeti beállítás a jelenlegi dark mode állapot alapján
await setupStatusBar(darkModeQuery.matches)
// Kis késleltetés hogy a UI renderelődjön
setTimeout(() => {
hideSplash()
}, 500)
})
// Haptics helper függvények exportálása
return {
provide: {
haptics: {
// Könnyű rezgés (pl. gomb kattintás)
light: () => Haptics.impact({ style: ImpactStyle.Light }),
// Közepes rezgés (pl. toggle váltás)
medium: () => Haptics.impact({ style: ImpactStyle.Medium }),
// Erős rezgés (pl. sikeres művelet)
heavy: () => Haptics.impact({ style: ImpactStyle.Heavy }),
// Szelekció rezgés
selection: () => Haptics.selectionStart(),
// Értesítés rezgések
success: () => Haptics.notification({ type: 'SUCCESS' as any }),
warning: () => Haptics.notification({ type: 'WARNING' as any }),
error: () => Haptics.notification({ type: 'ERROR' as any }),
}
}
}
})

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 202.3 80.17"
version="1.1"
id="svg48"
sodipodi:docname="euro_cars_rent_a_car_logo_light.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
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="namedview50"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="2.0335393"
inkscape:cx="146.05078"
inkscape:cy="33.439236"
inkscape:window-width="1920"
inkscape:window-height="1003"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Réteg_2" />
<defs
id="defs4">
<style
id="style2">
.cls-1 {
fill: #c7081c;
}
.cls-2 {
fill: #4d4d4dff;
}
.cls-3 {
fill: #696969ff;
}
.cls-4 {
fill: #464646ff;
}</style>
</defs>
<title
id="title6">euro_cars_rent_a_car_logo</title>
<g
id="Réteg_2"
data-name="Réteg 2">
<path
class="cls-1"
d="m 62.38,13.84 c 24.6,1.92 49.2,2.31 73.58,5.39 l -0.07,1 c -10.16,-0.54 -20.31,-1.17 -30.47,-1.58 -14.48,-0.59 -29,-0.93 -43.44,-1.55 -4,-0.18 -9,0.54 -12.16,4.58 h -4.4 a 23.91,23.91 0 0 1 3,-3.71 C 33.96,18.6 16.34,20.97 7.67,30.68 L 23.5,30.4 c 7.85,-5.51 18.09,-5.6 24.71,3.84 l -3.92,-0.06 c -6,-6.45 -12.38,-5.89 -17.31,-2.45 -2.46,1.72 -3.48,2.45 -3.48,2.45 H 0 c 0.16,-3.91 2.19,-6.53 4.76,-8.56 7.92,-6.26 17.32,-8.86 27,-10.33 7.27,-1.09 14.65,-1.43 22,-2.19 a 10.12,10.12 0 0 0 3.73,-1 A 97.19,97.19 0 0 1 102.81,0 c 20.17,-0.48 39.6,3.43 58.55,9.73 10.49,3.48 21.86,8.84 32.13,13 0.95,0.38 -0.29,1.21 -1,0.9 A 308.41,308.41 0 0 0 132,5.17 C 119,2.68 111,2.52 97.77,3 86.62,3.37 71.89,7.76 62.38,13.84 Z"
id="path8" />
<path
class="cls-2"
d="m 4,42.91 h 3.72 q 3.62,0 7.5,-0.06 l 0.11,0.12 -0.92,5 L 13.6,48 12.65,44.38 H 6.89 v 7.91 h 0.8 2.79 a 0.52,0.52 0 0 0 0.5,-0.41 l 0.54,-2 h 1 c 0,1.44 0,2.52 0,3.23 0,0.71 0,1.76 0,3.18 l -1,0.08 L 11,54.2 A 0.5,0.5 0 0 0 10.54,53.78 H 7.71 6.89 v 5.11 q 0,1.64 0,3.24 h 5.95 l 1.88,-3.91 0.91,-0.14 -0.36,5.57 -0.11,0.1 q -3.7,0 -7.21,0 H 4 c -1.28,0 -2.6,0 -4,0 V 63 L 2,62.45 A 0.5,0.5 0 0 0 2.4,62 c 0,-0.4 0,-0.84 0,-1.33 0,-0.49 0,-1 0,-1.63 V 47.15 c 0,-0.5 0,-0.95 0,-1.36 0,-0.41 0,-0.78 0,-1.11 A 0.48,0.48 0 0 0 2,44.19 L 0,43.61 v -0.76 q 2.09,0.06 4,0.06 z"
id="path10"
style="fill:#f9f9f9" />
<path
class="cls-2"
d="m 21.76,42.85 c 1.38,0 2.91,0.06 4.58,0.06 1.67,0 3.26,0 4.59,-0.06 l 0.07,0.76 -1.93,0.55 a 0.46,0.46 0 0 0 -0.39,0.44 c 0,0.36 0,0.74 0,1.16 0,0.42 0,0.85 0,1.33 v 8.2 q 0,4.07 1.22,5.62 a 4.74,4.74 0 0 0 4,1.55 4.94,4.94 0 0 0 4,-1.64 q 1.35,-1.65 1.35,-5.34 v -8.39 c 0,-0.48 0,-0.92 0,-1.33 0,-0.41 0,-0.8 0,-1.16 a 0.46,0.46 0 0 0 -0.39,-0.44 l -1.84,-0.52 v -0.79 c 1.32,0 2.47,0.06 3.43,0.06 0.96,0 2,0 3.36,-0.06 l 0.07,0.76 -2,0.58 a 0.48,0.48 0 0 0 -0.37,0.49 c 0,0.33 0,0.71 0,1.11 0,0.4 0,0.86 0,1.36 v 7.56 q 0,5.11 -2.11,7.34 a 8,8 0 0 1 -6.12,2.23 c -3.05,0 -5.29,-0.71 -6.74,-2.12 -1.45,-1.41 -2.17,-3.68 -2.17,-6.8 v -8.21 c 0,-0.5 0,-0.95 0,-1.36 0,-0.41 0,-0.78 0,-1.11 a 0.48,0.48 0 0 0 -0.36,-0.49 l -2,-0.58 z"
id="path12"
style="fill:#f9f9f9" />
<path
class="cls-2"
d="m 56.48,59 c 0,0.59 0,1.13 0,1.6 0,0.47 0,0.9 0,1.28 0,0.38 0.13,0.52 0.34,0.58 l 1.58,0.54 0.05,0.74 c -1.1,0 -2.47,0 -4.1,0 -1.63,0 -3.28,0 -4.64,0 L 49.64,63 l 2,-0.55 A 0.49,0.49 0 0 0 52,62 c 0,-0.4 0,-0.84 0,-1.33 0,-0.49 0,-1 0,-1.63 V 47.15 c 0,-0.5 0,-0.95 0,-1.36 0,-0.41 0,-0.78 0,-1.11 a 0.48,0.48 0 0 0 -0.35,-0.49 l -2,-0.58 v -0.76 c 1.39,0 2.81,0.06 4.27,0.06 h 1.14 l 1.67,-0.05 h 1.5 0.94 a 10.45,10.45 0 0 1 5.74,1.28 4.22,4.22 0 0 1 1.91,3.74 5.32,5.32 0 0 1 -1.17,3.58 7.46,7.46 0 0 1 -3.43,2.09 c 0.83,1.23 1.48,2.22 1.93,3 0.45,0.78 0.85,1.45 1.35,2.15 0.5,0.7 0.87,1.39 1.24,2 a 8.7,8.7 0 0 0 1.05,1.3 5.41,5.41 0 0 0 0.52,0.39 4.16,4.16 0 0 0 0.51,0.28 4.77,4.77 0 0 0 0.57,0.2 l 0.68,0.16 0.06,0.75 a 23.68,23.68 0 0 1 -3.34,0.21 7.64,7.64 0 0 1 -2.08,-0.19 3.44,3.44 0 0 1 -1.06,-0.55 5.93,5.93 0 0 1 -1.25,-1.4 c -0.38,-0.58 -0.79,-1.23 -1.22,-2 -0.43,-0.77 -0.86,-1.49 -1.31,-2.31 -0.45,-0.82 -0.93,-1.61 -1.42,-2.41 L 58.08,54.57 A 1.45,1.45 0 0 0 57.8,54.23 1,1 0 0 0 57.5,54.07 1.3,1.3 0 0 0 57.11,54 h -0.63 z m 0,-6.27 c 0.53,0 1,0 1.43,0 a 4,4 0 0 0 3.09,-1.01 4.81,4.81 0 0 0 1,-3.32 4.52,4.52 0 0 0 -1,-3.19 3.86,3.86 0 0 0 -2.94,-1 h -0.73 l -0.89,0.09 z"
id="path14"
style="fill:#f9f9f9" />
<path
class="cls-2"
d="m 96.71,52.82 a 11.38,11.38 0 0 1 -3,8.28 q -3,3.13 -8.45,3.13 -5.18,0 -8,-2.89 a 10.73,10.73 0 0 1 -2.83,-7.84 10.89,10.89 0 0 1 3,-8.15 c 2,-2 4.85,-3 8.44,-3 3.59,0 6.12,0.93 8,2.8 a 10.28,10.28 0 0 1 2.84,7.67 z M 79.39,53 c 0,3.17 0.53,5.6 1.61,7.28 a 5.22,5.22 0 0 0 4.71,2.53 5,5 0 0 0 4.53,-2.29 q 1.47,-2.3 1.47,-7.21 a 13.46,13.46 0 0 0 -1.55,-7.09 5.25,5.25 0 0 0 -4.79,-2.48 5,5 0 0 0 -4.56,2.3 C 79.86,47.59 79.39,49.9 79.39,53 Z"
id="path16"
style="fill:#f9f9f9" />
<path
class="cls-2"
d="m 131.21,48.47 -0.82,0.14 -1.13,-4.28 a 8.61,8.61 0 0 0 -2.54,-0.37 5.92,5.92 0 0 0 -5.09,2.47 10.67,10.67 0 0 0 -1.8,6.45 10.17,10.17 0 0 0 2.17,6.78 7.24,7.24 0 0 0 5.88,2.53 12.74,12.74 0 0 0 4.42,-0.85 l 0.2,0.85 a 11.71,11.71 0 0 1 -6.73,2 10.75,10.75 0 0 1 -7.86,-2.94 10.29,10.29 0 0 1 -3,-7.72 10.33,10.33 0 0 1 3.29,-8.08 12.31,12.31 0 0 1 8.58,-3 25,25 0 0 1 5.36,0.61 l 0.09,0.15 z"
id="path18"
style="fill:#f9f9f9" />
<path
class="cls-2"
d="m 143.11,57.07 -1.06,2.79 c -0.21,0.54 -0.37,1 -0.48,1.31 a 2.53,2.53 0 0 0 -0.18,0.77 0.53,0.53 0 0 0 0.14,0.39 0.91,0.91 0 0 0 0.42,0.2 l 1.42,0.42 v 0.77 c -1.44,0 -2.61,0 -3.51,0 -0.9,0 -2,0 -3.23,0 L 136.6,63 138.2,62.52 A 1.46,1.46 0 0 0 139,62 a 6,6 0 0 0 0.59,-1.15 l 7.41,-18.09 1.61,-0.24 6.42,18.09 a 4.85,4.85 0 0 0 0.67,1.41 1.81,1.81 0 0 0 0.87,0.53 l 1.46,0.43 0.05,0.74 c -1.34,0 -2.69,0 -4.05,0 -1.8,0 -3.55,0 -5.25,0 l -0.08,-0.74 1.47,-0.43 a 1.06,1.06 0 0 0 0.44,-0.22 0.56,0.56 0 0 0 0.13,-0.41 2.88,2.88 0 0 0 -0.15,-0.78 c -0.1,-0.32 -0.24,-0.74 -0.43,-1.27 l -1,-2.8 z m 3.21,-8.54 c -0.18,0.52 -0.37,1 -0.58,1.61 l -2,5.39 h 5 l -1.83,-5.38 c -0.26,-0.56 -0.43,-1.1 -0.59,-1.62 z"
id="path20"
style="fill:#f9f9f9" />
<path
class="cls-2"
d="m 170,59 v 1.6 c 0,0.47 0,0.9 0,1.28 0,0.38 0.12,0.52 0.34,0.58 l 1.55,0.51 v 0.74 c -1.1,0 -2.47,0 -4.09,0 -1.62,0 -3.29,0 -4.65,0 l -0.07,-0.74 2,-0.55 a 0.5,0.5 0 0 0 0.41,-0.46 c 0,-0.4 0,-0.84 0,-1.33 0,-0.49 0,-1 0,-1.63 V 47.15 c 0,-0.5 0,-0.95 0,-1.36 0,-0.41 0,-0.78 0,-1.11 a 0.48,0.48 0 0 0 -0.36,-0.49 l -2,-0.58 v -0.76 c 1.39,0 2.81,0.06 4.27,0.06 h 1.15 l 1.66,-0.05 h 1.5 0.94 a 10.43,10.43 0 0 1 5.74,1.28 4.2,4.2 0 0 1 1.91,3.74 5.37,5.37 0 0 1 -1.16,3.58 7.52,7.52 0 0 1 -3.43,2.09 c 0.83,1.23 1.47,2.22 1.92,3 0.45,0.78 0.89,1.45 1.37,2.15 0.48,0.7 0.87,1.39 1.25,2 a 8.7,8.7 0 0 0 1.02,1.3 5.34,5.34 0 0 0 0.51,0.39 4.16,4.16 0 0 0 0.51,0.28 4.38,4.38 0 0 0 0.58,0.2 l 0.67,0.16 0.06,0.75 a 23.53,23.53 0 0 1 -3.33,0.21 7.59,7.59 0 0 1 -2.08,-0.19 3.44,3.44 0 0 1 -1.06,-0.55 5.75,5.75 0 0 1 -1.26,-1.4 c -0.38,-0.58 -0.79,-1.23 -1.21,-2 -0.42,-0.77 -0.87,-1.49 -1.32,-2.31 -0.45,-0.82 -0.92,-1.61 -1.42,-2.41 l -0.36,-0.56 a 1.46,1.46 0 0 0 -0.29,-0.34 0.92,0.92 0 0 0 -0.29,-0.16 1.44,1.44 0 0 0 -0.4,-0.07 H 170 Z m 0,-6.27 c 0.52,0 1,0 1.42,0 a 4,4 0 0 0 3.1,-1.07 4.81,4.81 0 0 0 1,-3.32 4.52,4.52 0 0 0 -0.94,-3.19 3.86,3.86 0 0 0 -2.94,-1 h -0.74 l -0.88,0.09 z"
id="path22"
style="fill:#f9f9f9" />
<path
class="cls-2"
d="m 198.75,44.26 a 5.55,5.55 0 0 0 -2.06,-0.37 4,4 0 0 0 -2.67,0.92 3,3 0 0 0 -1.1,2.38 2.92,2.92 0 0 0 0.36,1.5 4,4 0 0 0 0.95,1.12 7.4,7.4 0 0 0 1.36,0.88 c 0.51,0.26 1,0.51 1.59,0.77 0.59,0.26 1.21,0.61 1.83,0.95 a 8,8 0 0 1 1.65,1.22 5.4,5.4 0 0 1 1.18,1.69 5.52,5.52 0 0 1 0.46,2.38 5.62,5.62 0 0 1 -2.3,4.74 9.64,9.64 0 0 1 -6,1.73 17,17 0 0 1 -5.31,-0.85 l -0.09,-0.13 0.78,-5.36 0.93,-0.15 1.11,4.56 a 5.79,5.79 0 0 0 2.38,0.49 4.62,4.62 0 0 0 3.05,-1 3.17,3.17 0 0 0 1.15,-2.53 3.08,3.08 0 0 0 -0.36,-1.54 3.94,3.94 0 0 0 -1,-1.13 7.7,7.7 0 0 0 -1.39,-0.89 l -1.6,-0.77 c -0.61,-0.3 -1.22,-0.61 -1.82,-0.94 a 6.65,6.65 0 0 1 -1.62,-1.19 5.26,5.26 0 0 1 -1.16,-1.67 5.61,5.61 0 0 1 -0.45,-2.36 5.4,5.4 0 0 1 2.17,-4.52 8.91,8.91 0 0 1 5.64,-1.69 21.38,21.38 0 0 1 5,0.69 l 0.09,0.13 -0.91,4.79 -0.82,0.14 z"
id="path24"
style="fill:#f9f9f9" />
<path
class="cls-3"
d="m 54.81,77.56 v 0.8 c 0,0.24 0,0.45 0,0.65 a 0.29,0.29 0 0 0 0.18,0.29 l 0.77,0.25 v 0.37 h -2 -2.33 v -0.37 l 1,-0.27 a 0.25,0.25 0 0 0 0.2,-0.24 c 0,-0.19 0,-0.42 0,-0.66 V 71 c 0,-0.21 0,-0.39 0,-0.56 a 0.24,0.24 0 0 0 -0.17,-0.25 l -1,-0.29 v -0.38 q 1,0 2.13,0 h 0.58 0.83 0.75 0.47 A 5.19,5.19 0 0 1 59.09,70.16 2.11,2.11 0 0 1 60,72 2.64,2.64 0 0 1 59.42,73.79 3.61,3.61 0 0 1 57.7,74.84 c 0.42,0.61 0.74,1.11 1,1.49 0.26,0.38 0.45,0.76 0.68,1.13 0.23,0.37 0.43,0.7 0.62,1 a 4.77,4.77 0 0 0 0.52,0.67 l 0.26,0.19 a 0.94,0.94 0 0 0 0.26,0.14 l 0.28,0.11 0.34,0.07 v 0.38 a 11.63,11.63 0 0 1 -1.66,0.11 4,4 0 0 1 -1,-0.1 1.83,1.83 0 0 1 -0.52,-0.27 3.07,3.07 0 0 1 -0.63,-0.7 c -0.19,-0.29 -0.4,-0.62 -0.61,-1 L 56.58,76.91 C 56.36,76.5 56.12,76.1 55.87,75.7 L 55.69,75.42 A 0.9,0.9 0 0 0 55.55,75.25 L 55.4,75.17 a 0.56,0.56 0 0 0 -0.2,0 h -0.31 z m 0,-3.13 c 0.26,0 0.5,0 0.71,0 a 2,2 0 0 0 1.55,-0.53 2.37,2.37 0 0 0 0.49,-1.66 2.32,2.32 0 0 0 -0.47,-1.6 2,2 0 0 0 -1.47,-0.5 h -0.37 -0.44 z"
id="path26"
style="fill:#f9f9f9" />
<path
class="cls-3"
d="m 65.33,69.51 h 1.88 3.75 l 0.05,0.06 -0.46,2.43 -0.4,0.06 -0.48,-1.81 H 66.8 v 4 h 1.79 a 0.26,0.26 0 0 0 0.25,-0.2 l 0.27,-1 h 0.49 c 0,0.72 0,1.25 0,1.61 0,0.36 0,0.88 0,1.59 h -0.49 l -0.28,-1 A 0.25,0.25 0 0 0 68.6,75 h -1.8 v 2.55 c 0,0.55 0,1.09 0,1.62 h 3 l 0.93,-2 0.46,-0.07 -0.19,2.77 v 0 h -3.61 -2 -2 V 79.5 l 1,-0.27 a 0.27,0.27 0 0 0 0.2,-0.24 c 0,-0.19 0,-0.42 0,-0.66 V 71 c 0,-0.21 0,-0.39 0,-0.56 a 0.26,0.26 0 0 0 -0.18,-0.25 l -1,-0.29 v -0.38 z"
id="path28"
style="fill:#f9f9f9" />
<path
class="cls-3"
d="m 75.76,79 a 0.25,0.25 0 0 0 0.19,0.26 l 1,0.26 V 79.9 H 75.3 73.62 v -0.37 l 1,-0.27 a 0.26,0.26 0 0 0 0.21,-0.24 c 0,-0.4 0,-0.89 0,-1.48 v -5.91 c 0,-0.49 0,-0.9 0,-1.23 a 0.26,0.26 0 0 0 -0.18,-0.25 l -1,-0.29 v -0.38 h 1.6 q 0.72,0 1.38,0 l 4.95,6.2 0.61,0.79 c 0,-0.34 0,-0.67 0,-1 V 71.6 c 0,-0.48 0,-0.89 0,-1.24 A 0.23,0.23 0 0 0 82,70.14 l -1,-0.26 v -0.4 h 1.67 1.66 v 0.38 l -1,0.29 a 0.26,0.26 0 0 0 -0.18,0.25 c 0,0.33 0,0.74 0,1.23 v 8.27 l -0.95,0.1 -5.87,-7.34 -0.6,-0.8 c 0,0.37 0,0.71 0,1 v 4.71 c 0.02,0.58 0.02,1.06 0.03,1.43 z"
id="path30"
style="fill:#f9f9f9" />
<path
class="cls-3"
d="m 90.6,79.9 h -2.5 v -0.37 l 1.19,-0.33 a 0.25,0.25 0 0 0 0.19,-0.23 c 0,-0.38 0,-0.86 0,-1.44 v -7.25 h -2.16 l -0.68,2 -0.42,0.07 L 86,69.54 v -0.06 h 3.5 2.08 3.53 v 0.06 l -0.49,2.73 -0.42,0.06 -0.48,-2 h -2.03 v 7.27 c 0,0.58 0,1.06 0,1.44 a 0.26,0.26 0 0 0 0.21,0.23 l 1.16,0.33 v 0.37 z"
id="path32"
style="fill:#f9f9f9" />
<path
class="cls-3"
d="m 103.67,76.6 -0.52,1.4 c -0.11,0.27 -0.19,0.49 -0.25,0.66 a 1.43,1.43 0 0 0 -0.08,0.38 0.24,0.24 0 0 0 0.07,0.19 0.42,0.42 0 0 0 0.2,0.11 l 0.72,0.21 v 0.38 h -1.76 -1.61 v -0.37 l 0.8,-0.24 a 0.71,0.71 0 0 0 0.42,-0.27 4.14,4.14 0 0 0 0.29,-0.57 l 3.71,-9 0.8,-0.12 3.21,9.05 a 2.36,2.36 0 0 0 0.34,0.7 0.89,0.89 0 0 0 0.43,0.27 l 0.73,0.21 v 0.37 h -2 -2.63 v -0.37 l 0.73,-0.21 a 0.51,0.51 0 0 0 0.22,-0.12 0.28,0.28 0 0 0 0.07,-0.2 1.41,1.41 0 0 0 -0.08,-0.39 l -0.21,-0.63 -0.5,-1.4 z m 1.61,-4.27 c -0.09,0.25 -0.18,0.52 -0.29,0.8 l -1,2.69 h 2.49 l -0.92,-2.68 z"
id="path34"
style="fill:#f9f9f9" />
<path
class="cls-3"
d="m 125.82,72.3 -0.41,0.06 -0.57,-2.13 a 4,4 0 0 0 -1.27,-0.19 3,3 0 0 0 -2.57,1.23 5.35,5.35 0 0 0 -0.9,3.23 5.13,5.13 0 0 0 1.06,3.39 3.63,3.63 0 0 0 2.95,1.27 6.31,6.31 0 0 0 2.21,-0.43 l 0.09,0.43 a 5.86,5.86 0 0 1 -3.36,1 5.37,5.37 0 0 1 -3.93,-1.47 5.14,5.14 0 0 1 -1.5,-3.86 5.19,5.19 0 0 1 1.64,-4 6.18,6.18 0 0 1 4.3,-1.49 11.84,11.84 0 0 1 2.67,0.31 v 0.07 z"
id="path36"
style="fill:#f9f9f9" />
<path
class="cls-3"
d="m 131,76.6 -0.53,1.4 -0.24,0.66 a 1.18,1.18 0 0 0 -0.09,0.38 0.27,0.27 0 0 0 0.07,0.19 0.52,0.52 0 0 0 0.21,0.11 l 0.71,0.21 v 0.38 h -1.76 -1.61 v -0.37 l 0.8,-0.24 A 0.71,0.71 0 0 0 129,79 a 3.17,3.17 0 0 0 0.3,-0.57 l 3.71,-9 0.8,-0.12 3.19,9.06 a 2.4,2.4 0 0 0 0.33,0.7 1,1 0 0 0 0.44,0.27 l 0.73,0.21 v 0.37 h -2 -2.63 v -0.37 l 0.74,-0.21 a 0.51,0.51 0 0 0 0.22,-0.12 0.28,0.28 0 0 0 0.06,-0.2 1.34,1.34 0 0 0 -0.07,-0.39 c 0,-0.16 -0.12,-0.37 -0.22,-0.63 l -0.49,-1.4 z m 1.61,-4.27 -0.29,0.8 -1,2.69 h 2.48 l -0.91,-2.68 c -0.12,-0.29 -0.2,-0.56 -0.28,-0.81 z"
id="path38"
style="fill:#f9f9f9" />
<path
class="cls-3"
d="m 143.66,77.56 c 0,0.3 0,0.57 0,0.8 0,0.23 0,0.45 0,0.65 a 0.27,0.27 0 0 0 0.17,0.29 l 0.77,0.25 v 0.37 h -2.05 -2.32 v -0.37 l 1,-0.27 a 0.27,0.27 0 0 0 0.2,-0.24 c 0,-0.19 0,-0.42 0,-0.66 V 71 c 0,-0.21 0,-0.39 0,-0.56 a 0.26,0.26 0 0 0 -0.18,-0.25 l -1,-0.29 v -0.38 c 0.69,0 1.41,0 2.14,0 h 0.61 0.83 0.75 0.42 a 5.17,5.17 0 0 1 2.87,0.64 2.09,2.09 0 0 1 1,1.86 2.65,2.65 0 0 1 -0.59,1.79 3.62,3.62 0 0 1 -1.71,1.05 c 0.41,0.61 0.74,1.11 1,1.49 0.26,0.38 0.45,0.76 0.68,1.13 l 0.62,1 a 4.11,4.11 0 0 0 0.53,0.67 c 0.09,0.07 0.17,0.14 0.25,0.19 a 1.1,1.1 0 0 0 0.26,0.14 l 0.29,0.11 0.34,0.07 v 0.38 a 11.89,11.89 0 0 1 -1.67,0.11 4,4 0 0 1 -1,-0.1 1.76,1.76 0 0 1 -0.53,-0.27 3.07,3.07 0 0 1 -0.63,-0.7 c -0.19,-0.29 -0.39,-0.62 -0.61,-1 -0.22,-0.38 -0.43,-0.75 -0.65,-1.15 -0.22,-0.4 -0.47,-0.81 -0.71,-1.21 l -0.19,-0.28 a 0.49,0.49 0 0 0 -0.14,-0.17 l -0.15,-0.08 a 0.54,0.54 0 0 0 -0.19,0 h -0.32 z m 0,-3.13 c 0.27,0 0.5,0 0.72,0 a 2,2 0 0 0 1.55,-0.53 2.42,2.42 0 0 0 0.49,-1.66 2.27,2.27 0 0 0 -0.48,-1.6 1.93,1.93 0 0 0 -1.47,-0.5 h -0.36 -0.45 z"
id="path40"
style="fill:#f9f9f9" />
<path
class="cls-4"
d="M 23.29,72.68 H 45.15 V 75 H 0.24 c 0,0 15.76,-2.32 23.05,-2.32 z"
id="path42"
style="fill:#f9f9f9" />
<path
class="cls-4"
d="M 179,72.68 H 157.15 V 75 h 44.91 c 0,0 -15.8,-2.32 -23.06,-2.32 z"
id="path44"
style="fill:#f9f9f9" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,47 @@
{
"background_color": "#262626",
"icons": [
{
"src": "../icons/icon-48.webp",
"type": "image/png",
"sizes": "48x48",
"purpose": "any maskable"
},
{
"src": "../icons/icon-72.webp",
"type": "image/png",
"sizes": "72x72",
"purpose": "any maskable"
},
{
"src": "../icons/icon-96.webp",
"type": "image/png",
"sizes": "96x96",
"purpose": "any maskable"
},
{
"src": "../icons/icon-128.webp",
"type": "image/png",
"sizes": "128x128",
"purpose": "any maskable"
},
{
"src": "../icons/icon-192.webp",
"type": "image/png",
"sizes": "192x192",
"purpose": "any maskable"
},
{
"src": "../icons/icon-256.webp",
"type": "image/png",
"sizes": "256x256",
"purpose": "any maskable"
},
{
"src": "../icons/icon-512.webp",
"type": "image/png",
"sizes": "512x512",
"purpose": "any maskable"
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
resources/icon-only.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
resources/splash-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
resources/splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

45
stores/auth.ts Normal file
View File

@ -0,0 +1,45 @@
import { defineStore } from 'pinia'
export const useAuthStore = defineStore({
id: 'AuthStore',
state: () => ({ user: null, rentals: null, rent: {}, token: null }),
persist: {
storage: localStorage,
},
getters:{
token(){
return this.token
}
},
actions: {
async getData() {
const { getToken } = useAuthToken()
const { apiFetch } = useApi()
const token = getToken()
if (token) {
this.token = token
const { data } = await apiFetch('/me',
{
headers: {
'auth-key': token
}
}
)
if (data.value?.user) {
this.user = data.value.user
this.rentals = data.value.rentals
}
}
},
async logout() {
const { clearToken } = useAuthToken()
await clearToken()
this.user = null
this.rentals = null
this.token = null
this.rent = {}
navigateTo('/login')
}
}
})

7
stores/categories.ts Normal file
View File

@ -0,0 +1,7 @@
import { defineStore } from 'pinia'
export const useCategoriesStore = defineStore({
id: 'CategoriesStore',
state: () => ({ categories : null }),
actions: {}
})

11
stores/config.ts Normal file
View File

@ -0,0 +1,11 @@
import { defineStore } from 'pinia'
export const useMyConfigStore = defineStore({
id: 'myConfigStore',
state: () => ({ config: null, states:null }),
actions: {
async fetchData(){
}
}
})

7
stores/places.ts Normal file
View File

@ -0,0 +1,7 @@
import { defineStore } from 'pinia'
export const useMyPlacesStore = defineStore({
id: 'myPlacesStore',
state: () => ({ places:null }),
actions: {}
})

8
types/CategoryType.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
interface CategoryType{
category_id: Number,
shortname: String,
name: String,
price: String,
status: String,
image: String
}

12
types/PlaceType.d.ts vendored Normal file
View File

@ -0,0 +1,12 @@
interface PlaceType {
id: String,
icon: String,
name: String,
address: String,
price: String,
input: String,
office_place: String,
sort_order: String,
shortname: String,
color: String
}