This commit is contained in:
Juhász Ervin 2025-12-23 19:51:09 +01:00
parent ec735c7a4e
commit 76d6e30878
23 changed files with 8456 additions and 2311 deletions

2
.gitattributes vendored Normal file
View File

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

2
.gitignore vendored
View File

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

42
.ottotime Normal file
View File

@ -0,0 +1,42 @@
# 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-178:25

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

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

37
app.vue
View File

@ -1,5 +1,6 @@
<template> <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 /> <NuxtPage />
</div> </div>
</template> </template>
@ -50,11 +51,38 @@ nuxtApp.hooks.hook('app:mounted', async () => {
</script> </script>
<style> <style>
/* 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 { html {
font-size: 18px; font-size: 18px;
font-family: "Roboto", serif; 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-center {
text-align: center; text-align: center;
} }
@ -89,10 +117,13 @@ html {
border-left: 4px; border-left: 4px;
border-style: solid; border-style: solid;
} }
.p-disabled, .p-component:disabled{
.p-disabled,
.p-component:disabled {
opacity: 0.2; opacity: 0.2;
} }
pre{
pre {
font-size: 13px; font-size: 13px;
} }
</style> </style>

View File

@ -1,5 +1,5 @@
.p-toast { .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 { .p-toast-message {

27
capacitor.config.ts Normal file
View File

@ -0,0 +1,27 @@
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: false,
backgroundColor: '#262626',
androidScaleType: 'CENTER_CROP',
showSpinner: false,
splashFullScreen: true,
splashImmersive: true
},
StatusBar: {
style: 'DARK',
backgroundColor: '#262626'
}
},
android: {
backgroundColor: '#262626'
}
};
export default config;

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,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>

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
}
}]
}

View File

@ -0,0 +1,45 @@
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')
}
})

View File

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

View File

@ -1,31 +1,48 @@
{ {
"name": "nuxt-app", "name": "nuxt-app",
"type": "module", "type": "module",
"version": "1.0.1",
"versionCode": 2,
"scripts": { "scripts": {
"build": "nuxt build", "build": "nuxt build",
"dev": "nuxt dev", "dev": "nuxt dev",
"generate": "nuxt generate", "generate": "nuxt generate",
"preview": "nuxt preview", "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": { "devDependencies": {
"@capacitor/assets": "^3.0.5",
"@capacitor/cli": "^8.0.0",
"@iconify-json/ph": "^1.2.2", "@iconify-json/ph": "^1.2.2",
"@nuxt/icon": "1.10.3", "@nuxt/icon": "1.10.3",
"@pinia/nuxt": "0.9.0", "@pinia/nuxt": "0.9.0",
"@primevue/nuxt-module": "^4.2.5", "@primevue/nuxt-module": "^4.3.9",
"autoprefixer": "^10.4.20", "@vite-pwa/nuxt": "0.10.6",
"autoprefixer": "^10.4.21",
"nuxt": "3.15.0", "nuxt": "3.15.0",
"pinia": "^2.3.0", "pinia": "^2.3.1",
"postcss": "^8.4.49", "postcss": "^8.5.6",
"postcss-import": "^16.1.0" "postcss-import": "^16.1.1",
"typescript": "^5.9.3"
}, },
"dependencies": { "dependencies": {
"@capacitor/android": "^8.0.0",
"@capacitor/app": "^8.0.0",
"@capacitor/core": "^8.0.0",
"@capacitor/haptics": "^8.0.0",
"@capacitor/ios": "^8.0.0",
"@capacitor/splash-screen": "^8.0.0",
"@capacitor/status-bar": "^8.0.0",
"primeicons": "^7.0.0", "primeicons": "^7.0.0",
"primevue": "^4.2.5", "primevue": "^4.3.9",
"tailwindcss": "^3.4.17", "tailwindcss": "^3.4.17",
"tailwindcss-primeui": "^0.3.4", "tailwindcss-primeui": "^0.3.4",
"vue": "^3.5.13", "vue": "^3.5.21",
"vue-router": "^4.5.0" "vue-router": "^4.5.1"
}, },
"packageManager": "pnpm@9.14.4+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab" "packageManager": "pnpm@9.14.4+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab"
} }

View File

@ -86,7 +86,7 @@ onMounted(()=>{
<template #content> <template #content>
<div class="flex flex-wrap justify-center gap-1 items-center p-2 relative"> <div class="flex flex-wrap justify-center gap-1 items-center p-2 relative">
<CardLoading v-if="isLoading" /> <CardLoading v-if="isLoading" />
<InputOtp v-model="loginCodePrefix" :length="2" style="gap: 1" disabled size="small"> <InputOtp v-model="loginCodePrefix" :length="2" style="gap: 1; opacity:1" in disabled size="small">
</InputOtp> </InputOtp>
<div><i class="pi pi-minus"></i></div> <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> <InputOtp v-model="loginCode" :length="4" style="gap: 1" size="small" @change="changeCode($event)" integer-only></InputOtp>
@ -108,4 +108,8 @@ onMounted(()=>{
</template> </template>
<style></style> <style>
.p-disabled, .p-component:disabled
{
opacity: 0.9;
}</style>

View File

@ -6,64 +6,141 @@
<div class="px-3">Adataim</div> <div class="px-3">Adataim</div>
</div> </div>
<div class="p-3 space-y-3"> <div class="p-3 space-y-3">
<CardLoading v-if="isLoading" /> <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"> <FloatLabel variant="on">
<InputText id="name" v-model="user.nev" class="w-full" /> <InputText id="name" v-model="user.nev" class="w-full" :invalid="!user.nev" />
<label for="name">Név</label> <label for="name">Név</label>
</FloatLabel> </FloatLabel>
<FloatLabel variant="on"> <FloatLabel variant="on">
<InputText id="email" v-model="user.email" class="w-full" /> <InputText id="email" v-model="user.email" class="w-full" :invalid="!user.email" />
<label for="email">E-mail</label> <label for="email">E-mail</label>
</FloatLabel> </FloatLabel>
<FloatLabel variant="on"> <FloatLabel variant="on">
<InputText id="telefon" v-model="user.telefon" class="w-full" /> <InputText id="telefon" v-model="user.telefon" class="w-full" :invalid="!user.telefon" />
<label for="telefon">Telefon</label> <label for="telefon">Telefon</label>
</FloatLabel> </FloatLabel>
<FloatLabel variant="on"> <FloatLabel variant="on">
<InputText id="anyja_neve" v-model="user.anyja_neve" class="w-full" /> <InputText id="anyja_neve" v-model="user.anyja_neve" class="w-full" :invalid="!user.anyja_neve" />
<label for="anyja_neve">Anyja neve</label> <label for="anyja_neve">Anyja neve</label>
</FloatLabel> </FloatLabel>
<FloatLabel variant="on"> <FloatLabel variant="on">
<InputText id="szuletesi_hely" v-model="user.szuletesi_hely" class="w-full" /> <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> <label for="szuletesi_hely">Születési hely</label>
</FloatLabel> </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"> <FloatLabel variant="on">
<DatePicker show-icon date-format="yy-mm-dd" id="szuletesi_ido" v-model="user.szuletesi_ido" class="w-full" /> <InputText id="nemzetiseg" v-model="user.nemzetiseg" class="w-full" :invalid="!user.nemzetiseg" />
<label for="szuletesi_ido">Születési idő</label>
</FloatLabel>
<FloatLabel variant="on">
<InputText id="nemzetiseg" v-model="user.nemzetiseg" class="w-full" />
<label for="nemzetiseg">Állampolgárság</label> <label for="nemzetiseg">Állampolgárság</label>
</FloatLabel> </FloatLabel>
<FloatLabel variant="on"> <FloatLabel variant="on">
<InputText id="szigszam" v-model="user.szigszam" class="w-full" /> <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> <label for="szigszam">Személyi igazolvány / Útlevél száma</label>
</FloatLabel> </FloatLabel>
<FloatLabel variant="on"> <FloatLabel variant="on">
<InputText id="jogositvany_szama" v-model="user.jogositvany_szama" class="w-full" /> <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> <label for="jogositvany_szama">Jogosítvány száma</label>
</FloatLabel> </FloatLabel>
<FloatLabel variant="on"> <FloatLabel variant="on">
<InputText id="lakcim" v-model="user.lakcim" class="w-full" /> <InputText id="lakcim" v-model="user.lakcim" class="w-full" :invalid="!user.lakcim" />
<label for="lakcim">Lakcím</label> <label for="lakcim">Lakcím</label>
</FloatLabel> </FloatLabel>
<FloatLabel variant="on"> <div class="flex items-center gap-2">
<InputText id="tartozkodasicim" v-model="user.tartozkodasicim" class="w-full" /> <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> <label for="tartozkodasicim">Tartózkodási cím</label>
</FloatLabel> </FloatLabel>
<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>
<template #footer>
<Button label="Rendben" @click="showDialog = false" class="w-full" />
</template>
</Dialog>
<div class=""> <div class="">
<Button @click="save()" class="max-sm:w-full min-w-20" icon="pi pi-save">Adatok mentése</Button> <Button @click="save()" class="w-full min-w-20" icon="pi pi-save">Adatok mentése</Button>
</div> </div>
<pre>{{ rent }}</pre>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
const isLoading = ref() const isLoading = ref(false)
const { user } = storeToRefs(useAuthStore()) const sameAddress = ref(true)
async function save() { const { user, rent } = storeToRefs(useAuthStore())
const showDialog = ref(false)
const dialogType = ref<'success' | 'error'>('success')
const dialogMessage = 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 = useCookie('_auth')
const data = await $fetch<{ success: boolean; message: string }>('https://olcsoberauto.hu/rest/update_profile',
{
headers: {
'auth-key': token.value || ''
},
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'
}
showDialog.value = true
} }
</script> </script>

View File

@ -13,7 +13,13 @@
<div class="text-sm"><b>Lakcím: </b><br>{{ user.lakcim }}</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> <div class="text-sm"><b>Tartózkodási cím: </b><br>{{ user.tartozkodasicim }}</div>
<Message class="mt-2" severity="warn">Amennyiben adataidban változás történt, módosítsd a <i <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" severity="warn">Amennyiben adataidban változás történt, módosítsd a <i
class="pi pi-user mx-2"></i> profilodban.</Message> class="pi pi-user mx-2"></i> profilodban.</Message>
<div class="text-center"> <div class="text-center">
@ -24,7 +30,7 @@
<div class="p-card border-t border-t-4 border-primary"> <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>{{ <div v-if="rent.jaratszam" class="text-end text-xs pe-3"><span class="">járatszám:</span><b>{{
rent.jaratszam rent.jaratszam
}}</b></div> }}</b></div>
<div class="flex items-baseline flex-row"> <div class="flex items-baseline flex-row">
<div class="text-center p-2 w-full items-top"> <div class="text-center p-2 w-full items-top">
<div class="text-xs">{{ useLocaleDateString(rent.auto_felvetel_datum) }}</div> <div class="text-xs">{{ useLocaleDateString(rent.auto_felvetel_datum) }}</div>
@ -56,6 +62,27 @@
const { rent, user } = storeToRefs(useAuthStore()) const { rent, user } = storeToRefs(useAuthStore())
const { config } = storeToRefs(useMyConfigStore()) const { config } = storeToRefs(useMyConfigStore())
const confirms = ref([]) 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({ definePageMeta({
rentStep: 7, rentStep: 7,
@ -63,6 +90,7 @@ definePageMeta({
}) })
const isValid = computed(() => { const isValid = computed(() => {
if (!isUserDataValid.value) return true
if (config.value?.rent.confirms.length > confirms.value?.length) return true if (config.value?.rent.confirms.length > confirms.value?.length) return true
return false return false
}) })

View File

@ -0,0 +1,81 @@
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((nuxtApp) => {
// 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, kérdezzük meg hogy ki akar-e lépni
// vagy minimalizáljuk az appot
App.minimizeApp()
}
})
// Status bar beállítása
const setupStatusBar = async () => {
try {
// Sötét ikonok világos háttérrel (vagy fordítva dark mode-ban)
await StatusBar.setStyle({ style: Style.Dark })
// Android-on beállíthatjuk a háttérszínt
if (Capacitor.getPlatform() === 'android') {
await StatusBar.setBackgroundColor({ color: '#262626' }) // neutral-800
}
} 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)
}
}
// App mounted hook
nuxtApp.hooks.hook('app:mounted', async () => {
await setupStatusBar()
// 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

BIN
public/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

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