mirror of
https://git.hmsn.ink/kospo/svcm/dmz.git
synced 2026-03-20 09:03:44 +09:00
first
This commit is contained in:
189
src/pages/[...all].vue
Normal file
189
src/pages/[...all].vue
Normal file
@@ -0,0 +1,189 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* This is a Vue Component that will be
|
||||
* automatically mapped to a catch all path on vue-router (404).
|
||||
*
|
||||
* You will be able to access this page at http://localhost:3000/non-existing-page
|
||||
*
|
||||
* Read more about routing:
|
||||
* @see /vite.config.ts
|
||||
* @see /src/router.ts
|
||||
*/
|
||||
import type { VueroSSRContext } from '/@server/types'
|
||||
import { setResponseHeader, setResponseStatus } from 'h3'
|
||||
import { useSSRContext } from 'vue'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
useHead({
|
||||
title: `${t('pages.not-found.page-title')} - Vuero`,
|
||||
meta: [
|
||||
{
|
||||
name: 'robots',
|
||||
content: 'noindex',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
/**
|
||||
* When the route is not found, we want to send 404 error code
|
||||
* We do this by using the `useSSRContext` composable, then we use this to set the 404 status code
|
||||
* @see src/entry-server.ts
|
||||
* @see server.ts
|
||||
*/
|
||||
if (import.meta.env.SSR) {
|
||||
const event = useSSRContext<VueroSSRContext>()?.event
|
||||
if (event) {
|
||||
setResponseHeader(event, 'Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||
setResponseStatus(event, 404)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<MinimalLayout>
|
||||
<div class="error-container">
|
||||
<div class="error-nav">
|
||||
<VDarkmodeToggle />
|
||||
</div>
|
||||
|
||||
<div class="error-wrapper">
|
||||
<div class="error-inner has-text-centered">
|
||||
<div class="bg-number">
|
||||
404
|
||||
</div>
|
||||
<SVGErrorPlaceholder />
|
||||
|
||||
<h3>{{ t('pages.not-found.page-heading') }}</h3>
|
||||
<p>
|
||||
{{ t('pages.not-found.page-body') }}
|
||||
</p>
|
||||
<div class="button-wrap">
|
||||
<VButton
|
||||
color="primary"
|
||||
elevated
|
||||
to="/"
|
||||
>
|
||||
{{ t('pages.not-found.page-button') }}
|
||||
</VButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</MinimalLayout>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.error-container {
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
|
||||
.error-nav {
|
||||
.dark-mode {
|
||||
position: absolute;
|
||||
inset-inline-end: 0;
|
||||
top: 0;
|
||||
display: inline-block;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.error-wrapper {
|
||||
max-width: 840px;
|
||||
margin: 0 auto;
|
||||
padding-top: 40px;
|
||||
|
||||
.error-inner {
|
||||
position: relative;
|
||||
max-width: 540px;
|
||||
margin: 0 auto;
|
||||
|
||||
.bg-number {
|
||||
font-family: var(--font);
|
||||
position: absolute;
|
||||
top: -58px;
|
||||
inset-inline-start: -50px;
|
||||
inset-inline-end: 0;
|
||||
margin: 0 auto;
|
||||
font-size: 28rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.15;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
img,
|
||||
svg,
|
||||
h3,
|
||||
p,
|
||||
.button-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5rem;
|
||||
font-family: var(--font-alt);
|
||||
color: var(--dark-text);
|
||||
font-weight: 600;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: var(--font);
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
.button {
|
||||
min-width: 220px;
|
||||
min-height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-dark {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
.error-inner {
|
||||
.bg-number {
|
||||
opacity: 0.09;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (width <= 767px) {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
padding-top: 60px;
|
||||
|
||||
.error-inner {
|
||||
padding: 10px;
|
||||
|
||||
.bg-number {
|
||||
top: -35px;
|
||||
inset-inline-start: -18px;
|
||||
inset-inline-end: 0;
|
||||
font-size: 13rem;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
max-width: 345px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
5
src/pages/auth.vue
Normal file
5
src/pages/auth.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<AuthLayout>
|
||||
<RouterView />
|
||||
</AuthLayout>
|
||||
</template>
|
||||
856
src/pages/auth/login.vue
Normal file
856
src/pages/auth/login.vue
Normal file
@@ -0,0 +1,856 @@
|
||||
<script setup lang="ts">
|
||||
import api from '/@src/utils/api.ts'
|
||||
import type { UserData } from '/@src/utils/types'
|
||||
import regex from '/@src/utils/regex.ts'
|
||||
|
||||
type StepId = 'login' | 'forgot-password'
|
||||
const step = ref<StepId>('login')
|
||||
const isLoading = ref(false)
|
||||
const privacyModal = ref(false)
|
||||
const privacy = ref(false)
|
||||
const loginForm = ref(<UserData>{
|
||||
bizNo: '999-99-99999',
|
||||
pwd: 'kospo2025!',
|
||||
})
|
||||
|
||||
const forgetForm = ref(<UserData>{})
|
||||
const forgetValid = ref({
|
||||
email: true,
|
||||
bizNo: true,
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
const notyf = useNotyf()
|
||||
const token = useUserToken()
|
||||
const userSession = useUserSession()
|
||||
|
||||
const rules = {
|
||||
bizNo: {
|
||||
mask: '000-00-00000',
|
||||
lazy: false,
|
||||
},
|
||||
email: {
|
||||
mask: /^\S*@?\S*$/,
|
||||
lazy: false,
|
||||
},
|
||||
}
|
||||
|
||||
const onComplete = (e: any) => {
|
||||
loginForm.value.bizNo = e.value
|
||||
}
|
||||
|
||||
const onBizNoComplete = (e: any) => {
|
||||
forgetForm.value.bizNo = e.value
|
||||
}
|
||||
|
||||
const onEmailComplete = (e: any) => {
|
||||
forgetForm.value.email = e.value
|
||||
}
|
||||
|
||||
const handleLogin = async () => {
|
||||
if (!isLoading.value) {
|
||||
isLoading.value = true
|
||||
api.login(loginForm.value.bizNo, loginForm.value.pwd).then((result: UserData) => {
|
||||
token.value = result.accessToken
|
||||
userSession.setUser(result)
|
||||
notyf.dismissAll()
|
||||
notyf.primary(`환영합니다. ${result.repNm}님`)
|
||||
router.push('/navbar/dashboards')
|
||||
isLoading.value = false
|
||||
}).catch((res) => {
|
||||
notyf.error(res.response._data.body)
|
||||
console.log(res.response._data)
|
||||
if (res.response._data.code === '43003') {
|
||||
console.log('약관 활성화********')
|
||||
privacyModal.value = true
|
||||
}
|
||||
isLoading.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const forgetSubmit = () => {
|
||||
let submit = true
|
||||
notyf.dismissAll()
|
||||
forgetValid.value = {
|
||||
bizNo: true,
|
||||
email: true,
|
||||
}
|
||||
if (!regex.bizNo.test(forgetForm.value.bizNo)) {
|
||||
notyf.error('사업자번호가 정상적이지 않습니다. 다시 입력해주세요.')
|
||||
forgetValid.value.bizNo = false
|
||||
submit = false
|
||||
}
|
||||
if (!regex.email.test(forgetForm.value.email)) {
|
||||
notyf.error('이메일이 정상적이지 않습니다. 다시 입력해주세요.')
|
||||
forgetValid.value.email = false
|
||||
submit = false
|
||||
}
|
||||
if (submit) {
|
||||
step.value = 'login'
|
||||
}
|
||||
else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
useHead({
|
||||
title: '소액계약관리 - 로그인',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="modern-login">
|
||||
<div class="underlay h-hidden-mobile h-hidden-tablet-p" />
|
||||
|
||||
<div class="columns is-gapless is-vcentered">
|
||||
<div class="column is-relative is-8 h-hidden-mobile h-hidden-tablet-p">
|
||||
<div class="hero is-fullheight is-image">
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<img
|
||||
class="hero-image"
|
||||
src="/images/illustrations/login/station.svg"
|
||||
alt=""
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-4 is-relative">
|
||||
<div class="top-tools">
|
||||
<RouterLink
|
||||
to="/"
|
||||
class="top-logo"
|
||||
>
|
||||
<AnimatedLogo
|
||||
width="38px"
|
||||
height="38px"
|
||||
/>
|
||||
</RouterLink>
|
||||
|
||||
<VDarkmodeToggle />
|
||||
</div>
|
||||
<div class="is-form">
|
||||
<div class="is-form-inner">
|
||||
<div
|
||||
class="form-text"
|
||||
:class="[step !== 'login' && 'is-hidden']"
|
||||
>
|
||||
<h2>로그인</h2>
|
||||
<p>소액 관리 시스템</p>
|
||||
</div>
|
||||
<div
|
||||
class="form-text"
|
||||
:class="[step === 'login' && 'is-hidden']"
|
||||
>
|
||||
<h2>계정 복구</h2>
|
||||
<p>비밀번호를 초기화 합니다.</p>
|
||||
</div>
|
||||
<form
|
||||
method="post"
|
||||
novalidate
|
||||
:class="[step !== 'login' && 'is-hidden']"
|
||||
class="login-wrapper"
|
||||
@submit.prevent="handleLogin"
|
||||
>
|
||||
|
||||
<VField>
|
||||
<VControl icon="lnil lnil-user autv-icon">
|
||||
<VLabel class="auth-label">
|
||||
사업자 번호
|
||||
</VLabel>
|
||||
<VIMaskInput
|
||||
class="input v-input"
|
||||
:mask="Number"
|
||||
:model-value="loginForm.bizNo"
|
||||
:options="rules.bizNo"
|
||||
@complete="onComplete"
|
||||
placeholder="111-11-11111"
|
||||
autocomplete="username"
|
||||
/>
|
||||
</VControl>
|
||||
</VField>
|
||||
<VField>
|
||||
<VControl icon="lnil lnil-lock-alt autv-icon">
|
||||
<VLabel class="auth-label">
|
||||
비밀번호
|
||||
</VLabel>
|
||||
<VInput
|
||||
type="password"
|
||||
v-model="loginForm.pwd"
|
||||
placeholder="*********"
|
||||
autocomplete="current-password"
|
||||
/>
|
||||
</VControl>
|
||||
</VField>
|
||||
|
||||
<VField>
|
||||
<VControl class="is-flex">
|
||||
<a
|
||||
tabindex="0"
|
||||
role="button"
|
||||
@keydown.enter.prevent="step = 'forgot-password'"
|
||||
@click="step = 'forgot-password'"
|
||||
>
|
||||
비밀번호 찾기
|
||||
</a>
|
||||
</VControl>
|
||||
</VField>
|
||||
|
||||
<div class="button-wrap has-help">
|
||||
<VButton
|
||||
id="login-button"
|
||||
:loading="isLoading"
|
||||
color="primary"
|
||||
type="submit"
|
||||
size="big"
|
||||
rounded
|
||||
raised
|
||||
bold
|
||||
>
|
||||
확인
|
||||
</VButton>
|
||||
<span>
|
||||
또는
|
||||
<RouterLink to="/auth/signup">계정</RouterLink>
|
||||
을 만드세요.
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form
|
||||
method="post"
|
||||
novalidate
|
||||
:class="[step !== 'forgot-password' && 'is-hidden']"
|
||||
class="login-wrapper"
|
||||
@submit.prevent="forgetSubmit"
|
||||
>
|
||||
<p class="recover-text">
|
||||
회원가입시 입력한 이메일주소를 입력해주세요.
|
||||
임시 비밀번호를 이메일로 보내드리겠습니다.
|
||||
</p>
|
||||
|
||||
<VField>
|
||||
<VControl icon="lnil lnil-user autv-icon" :class="[!forgetValid.bizNo && 'valid-err']">
|
||||
<VLabel class="auth-label">
|
||||
사업자번호
|
||||
</VLabel>
|
||||
<VIMaskInput
|
||||
class="input v-input"
|
||||
mask="000-00-00000"
|
||||
:model-value="forgetForm.bizNo"
|
||||
:options="rules.bizNo"
|
||||
placeholder="111-11-11111"
|
||||
autocomplete="username"
|
||||
@complete="onBizNoComplete"
|
||||
/>
|
||||
</VControl>
|
||||
</VField>
|
||||
<VField>
|
||||
<VControl icon="lnil lnil-envelope autv-icon" :class="[!forgetValid.email && 'valid-err']">
|
||||
<VLabel class="auth-label">
|
||||
이메일 주소
|
||||
</VLabel>
|
||||
<VIMaskInput
|
||||
class="input v-input"
|
||||
:mask="String"
|
||||
:model-value="forgetForm.email"
|
||||
:options="rules.email"
|
||||
placeholder="kospo@kospo.co.kr"
|
||||
autocomplete="email"
|
||||
@complete="onEmailComplete"
|
||||
/>
|
||||
</VControl>
|
||||
</VField>
|
||||
<div class="button-wrap">
|
||||
<VButton
|
||||
color="white"
|
||||
size="big"
|
||||
lower
|
||||
rounded
|
||||
@click="step = 'login'"
|
||||
>
|
||||
취소
|
||||
</VButton>
|
||||
<VButton
|
||||
color="primary"
|
||||
size="big"
|
||||
type="submit"
|
||||
lower
|
||||
rounded
|
||||
solid
|
||||
>
|
||||
확인
|
||||
</VButton>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<VModal
|
||||
is="form"
|
||||
:open="privacyModal"
|
||||
novalidate
|
||||
title="개인정보 동의서"
|
||||
actions="right"
|
||||
cancel-label="취소"
|
||||
|
||||
size="big"
|
||||
@close="privacyModal = false"
|
||||
>
|
||||
<template #content>
|
||||
<Privacy/>
|
||||
</template>
|
||||
<template #cancel>
|
||||
<div class="checkbox-wrap">
|
||||
<VField horizontal>
|
||||
<div class="txt">개인정보 이용 및 수집 동의(필수)</div>
|
||||
<VCheckbox label="동의" v-model="privacy"/>
|
||||
</VField>
|
||||
</div>
|
||||
</template>
|
||||
<template #action>
|
||||
<VButton color="primary">확인</VButton>
|
||||
</template>
|
||||
</VModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.checkbox-wrap {
|
||||
.is-horizontal {
|
||||
justify-content: end;
|
||||
|
||||
.txt {
|
||||
line-height: 40px;
|
||||
padding-right: 10px;
|
||||
letter-spacing: -.45px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modern-login {
|
||||
position: relative;
|
||||
background: var(--white);
|
||||
min-height: 100vh;
|
||||
|
||||
.column {
|
||||
&.is-relative {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.hero {
|
||||
&.has-background-image {
|
||||
position: relative;
|
||||
|
||||
.hero-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #5d4298 !important;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.underlay {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
width: 66.6%;
|
||||
height: 100%;
|
||||
background: #fdfdfd;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.top-tools {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1.25rem;
|
||||
margin-bottom: 5rem;
|
||||
|
||||
.dark-mode {
|
||||
transform: scale(0.6);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.top-logo {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1;
|
||||
width: 200px;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 150px;
|
||||
//max-width: 50px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.iconify {
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-image {
|
||||
position: relative;
|
||||
border-inline-end: 1px solid var(--fade-grey);
|
||||
|
||||
.hero-image {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
display: block;
|
||||
margin: -80px auto 0;
|
||||
max-width: 60%;
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
.is-form {
|
||||
position: relative;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
|
||||
form {
|
||||
animation: fadeInLeft 0.5s;
|
||||
}
|
||||
|
||||
.form-text {
|
||||
padding: 0 20px;
|
||||
animation: fadeInLeft 0.5s;
|
||||
|
||||
h2 {
|
||||
font-family: var(--font-alt);
|
||||
font-weight: 400;
|
||||
font-size: 3rem;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--muted-grey);
|
||||
margin-top: 10px;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.recover-text {
|
||||
font-size: 0.9rem;
|
||||
color: var(--dark-text);
|
||||
}
|
||||
|
||||
.login-wrapper {
|
||||
padding: 30px 20px;
|
||||
|
||||
.control {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin-top: 16px;
|
||||
|
||||
.input {
|
||||
padding-top: 14px;
|
||||
height: 60px;
|
||||
border-radius: 10px;
|
||||
padding-inline-start: 55px;
|
||||
transition: all 0.3s; // transition-all test
|
||||
|
||||
&:focus {
|
||||
background: color-mix(in oklab, var(--fade-grey), white 6%);
|
||||
border-color: var(--placeholder);
|
||||
|
||||
~ .auth-label,
|
||||
~ .autv-icon .iconify {
|
||||
color: var(--muted-grey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error-text {
|
||||
color: var(--danger);
|
||||
font-size: 0.8rem;
|
||||
display: none;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.auth-label {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
inset-inline-start: 55px;
|
||||
font-size: 1.0rem;
|
||||
color: var(--dark-text);
|
||||
font-weight: 500;
|
||||
z-index: 2;
|
||||
transition: all 0.3s; // transition-all test
|
||||
}
|
||||
|
||||
.autv-icon,
|
||||
:deep(.autv-icon) {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-start: 0;
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 24px;
|
||||
color: var(--placeholder);
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
&.has-validation {
|
||||
.validation-icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
inset-inline-end: 0;
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.icon-wrapper {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: var(--radius-rounded);
|
||||
|
||||
.iconify {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
stroke-width: 3px;
|
||||
color: var(--white);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-success {
|
||||
.icon-wrapper {
|
||||
background: var(--success);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-error {
|
||||
.icon-wrapper {
|
||||
background: var(--danger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.has-success {
|
||||
.validation-icon {
|
||||
&.is-success {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&.is-error {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.has-error {
|
||||
.input {
|
||||
border-color: var(--danger);
|
||||
}
|
||||
|
||||
.error-text {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.validation-icon {
|
||||
&.is-error {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&.is-success {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
margin-inline-start: auto;
|
||||
color: var(--muted-grey);
|
||||
font-weight: 500;
|
||||
font-size: 1.1rem;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
.remember-me {
|
||||
font-size: 0.9rem;
|
||||
color: var(--muted-grey);
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
margin: 40px 0;
|
||||
|
||||
&.has-help {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> span {
|
||||
margin-inline-start: 12px;
|
||||
font-family: var(--font);
|
||||
|
||||
a {
|
||||
color: var(--primary);
|
||||
font-weight: 500;
|
||||
padding: 0 2px;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
height: 46px;
|
||||
width: 140px;
|
||||
margin-inline-start: 6px;
|
||||
font-size: 1.1em;
|
||||
|
||||
&:first-child {
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.remember-toggle {
|
||||
width: 65px;
|
||||
display: block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
font-size: 22px;
|
||||
user-select: none;
|
||||
transform: scale(0.9);
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&:checked ~ .toggler {
|
||||
border-color: var(--primary);
|
||||
|
||||
.active,
|
||||
.inactive {
|
||||
transform: translateX(calc(var(--transform-direction) * 100%)) rotate(360deg);
|
||||
}
|
||||
|
||||
.active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.inactive {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toggler {
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 34px;
|
||||
width: 61px;
|
||||
border: 2px solid var(--placeholder);
|
||||
border-radius: 100px;
|
||||
transition: all 0.3s; // transition-all test
|
||||
|
||||
.active,
|
||||
.inactive {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
inset-inline-start: 2px;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
border-radius: var(--radius-rounded);
|
||||
background: black;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transform: translateX(calc(var(--transform-direction) * 0))
|
||||
rotate(calc(var(--transform-direction) * 0));
|
||||
transition: all 0.3s ease;
|
||||
|
||||
.iconify {
|
||||
color: var(--white);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.inactive {
|
||||
background: var(--placeholder);
|
||||
border-color: var(--placeholder);
|
||||
opacity: 1;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.active {
|
||||
background: var(--primary);
|
||||
border-color: var(--primary);
|
||||
opacity: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (width <= 767px) {
|
||||
.modern-login {
|
||||
.top-logo {
|
||||
top: 30px;
|
||||
}
|
||||
|
||||
.dark-mode {
|
||||
top: 36px;
|
||||
inset-inline-end: 44px;
|
||||
}
|
||||
|
||||
.is-form {
|
||||
padding-top: 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (width >= 768px) and (width <= 1024px) and (orientation: portrait) {
|
||||
.modern-login {
|
||||
.top-logo {
|
||||
.iconify {
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.dark-mode {
|
||||
top: -58px;
|
||||
inset-inline-end: 30%;
|
||||
}
|
||||
|
||||
.columns {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Dark mode
|
||||
========================================================================== */
|
||||
|
||||
.is-dark {
|
||||
.modern-login {
|
||||
background: var(--dark-sidebar);
|
||||
|
||||
.underlay {
|
||||
background: color-mix(in oklab, var(--dark-sidebar), white 10%);
|
||||
}
|
||||
|
||||
.is-image {
|
||||
border-color: color-mix(in oklab, var(--dark-sidebar), white 10%);
|
||||
}
|
||||
|
||||
.is-form {
|
||||
.form-text {
|
||||
h2 {
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
.login-wrapper {
|
||||
.control {
|
||||
&.is-flex {
|
||||
a:hover {
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
background: color-mix(in oklab, var(--dark-sidebar), white 4%);
|
||||
|
||||
&:focus {
|
||||
border-color: var(--primary);
|
||||
|
||||
~ .autv-icon {
|
||||
.iconify {
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.auth-label {
|
||||
color: var(--light-text);
|
||||
}
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
&.has-help {
|
||||
span {
|
||||
color: var(--light-text);
|
||||
|
||||
a {
|
||||
color: var(--primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.remember-toggle {
|
||||
input {
|
||||
&:checked + .toggler {
|
||||
border-color: var(--primary);
|
||||
|
||||
> span {
|
||||
background: var(--primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toggler {
|
||||
border-color: color-mix(in oklab, var(--dark-sidebar), white 12%);
|
||||
|
||||
> span {
|
||||
background: color-mix(in oklab, var(--dark-sidebar), white 12%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
1543
src/pages/auth/signup.vue
Normal file
1543
src/pages/auth/signup.vue
Normal file
File diff suppressed because it is too large
Load Diff
5
src/pages/error.vue
Normal file
5
src/pages/error.vue
Normal file
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<MinimalLayout>
|
||||
<RouterView />
|
||||
</MinimalLayout>
|
||||
</template>
|
||||
155
src/pages/error/page-1.vue
Normal file
155
src/pages/error/page-1.vue
Normal file
@@ -0,0 +1,155 @@
|
||||
<script setup lang="ts">
|
||||
useHead({
|
||||
title: 'Error Page 1 - Vuero',
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="error-container">
|
||||
<div class="error-nav">
|
||||
<VDarkmodeToggle />
|
||||
</div>
|
||||
<div class="error-wrapper">
|
||||
<div class="error-inner has-text-centered">
|
||||
<div class="bg-number dark-inverted">
|
||||
404
|
||||
</div>
|
||||
<SVGErrorPlaceholder />
|
||||
|
||||
<h3 class="dark-inverted">
|
||||
We couldn't find that page
|
||||
</h3>
|
||||
<p>
|
||||
Looks like we couldn't find that page. Please try again or contact an
|
||||
administrator if the problem persists.
|
||||
</p>
|
||||
<div class="button-wrap">
|
||||
<VButton
|
||||
color="primary"
|
||||
elevated
|
||||
@click="() => router.go(-1)"
|
||||
>
|
||||
Take me Back
|
||||
</VButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.error-container {
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
|
||||
.error-nav {
|
||||
.dark-mode {
|
||||
position: absolute;
|
||||
inset-inline-end: 0;
|
||||
top: 0;
|
||||
display: inline-block;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.error-wrapper {
|
||||
max-width: 840px;
|
||||
margin: 0 auto;
|
||||
padding-top: 40px;
|
||||
|
||||
.error-inner {
|
||||
position: relative;
|
||||
max-width: 540px;
|
||||
margin: 0 auto;
|
||||
|
||||
.bg-number {
|
||||
font-family: var(--font);
|
||||
position: absolute;
|
||||
top: -58px;
|
||||
inset-inline-start: -50px;
|
||||
inset-inline-end: 0;
|
||||
margin: 0 auto;
|
||||
font-size: 28rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.15;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
img,
|
||||
svg,
|
||||
h3,
|
||||
p,
|
||||
.button-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5rem;
|
||||
font-family: var(--font-alt);
|
||||
color: var(--dark-text);
|
||||
font-weight: 600;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: var(--font);
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
.button {
|
||||
min-width: 220px;
|
||||
min-height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-dark {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
.error-inner {
|
||||
.bg-number {
|
||||
opacity: 0.09;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (width <= 767px) {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
padding-top: 60px;
|
||||
|
||||
.error-inner {
|
||||
padding: 10px;
|
||||
|
||||
.bg-number {
|
||||
top: -35px;
|
||||
inset-inline-start: -18px;
|
||||
inset-inline-end: 0;
|
||||
font-size: 13rem;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
max-width: 345px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
164
src/pages/error/page-2.vue
Normal file
164
src/pages/error/page-2.vue
Normal file
@@ -0,0 +1,164 @@
|
||||
<script setup lang="ts">
|
||||
useHead({
|
||||
title: 'Error Page 2 - Vuero',
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="error-container">
|
||||
<div class="error-nav">
|
||||
<VDarkmodeToggle />
|
||||
</div>
|
||||
|
||||
<div class="error-wrapper">
|
||||
<div class="error-inner has-text-centered">
|
||||
<div class="bg-number dark-inverted">
|
||||
404
|
||||
</div>
|
||||
<img
|
||||
class="light-image"
|
||||
src="/images/illustrations/placeholders/error-2.svg"
|
||||
alt=""
|
||||
>
|
||||
<img
|
||||
class="dark-image"
|
||||
src="/images/illustrations/placeholders/error-2-dark.svg"
|
||||
alt=""
|
||||
>
|
||||
<h3 class="dark-inverted">
|
||||
We couldn't find that page
|
||||
</h3>
|
||||
<p>
|
||||
Looks like we couldn't find that page. Please try again or contact an
|
||||
administrator if the problem persists.
|
||||
</p>
|
||||
<div class="button-wrap">
|
||||
<VButton
|
||||
color="primary"
|
||||
elevated
|
||||
@click="() => router.go(-1)"
|
||||
>
|
||||
Take me Back
|
||||
</VButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.error-container {
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
|
||||
.error-nav {
|
||||
.dark-mode {
|
||||
position: absolute;
|
||||
inset-inline-end: 0;
|
||||
top: 0;
|
||||
display: inline-block;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.error-wrapper {
|
||||
max-width: 840px;
|
||||
margin: 0 auto;
|
||||
padding-top: 40px;
|
||||
|
||||
.error-inner {
|
||||
position: relative;
|
||||
max-width: 540px;
|
||||
margin: 0 auto;
|
||||
|
||||
.bg-number {
|
||||
font-family: var(--font);
|
||||
position: absolute;
|
||||
top: -58px;
|
||||
inset-inline-start: -50px;
|
||||
inset-inline-end: 0;
|
||||
margin: 0 auto;
|
||||
font-size: 28rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.15;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
img,
|
||||
svg,
|
||||
h3,
|
||||
p,
|
||||
.button-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5rem;
|
||||
font-family: var(--font-alt);
|
||||
color: var(--dark-text);
|
||||
font-weight: 600;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: var(--font);
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
.button {
|
||||
min-width: 220px;
|
||||
min-height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-dark {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
.error-inner {
|
||||
.bg-number {
|
||||
opacity: 0.09;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (width <= 767px) {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
padding-top: 60px;
|
||||
|
||||
.error-inner {
|
||||
padding: 10px;
|
||||
|
||||
.bg-number {
|
||||
top: -35px;
|
||||
inset-inline-start: -18px;
|
||||
inset-inline-end: 0;
|
||||
font-size: 13rem;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
max-width: 345px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
162
src/pages/error/page-3.vue
Normal file
162
src/pages/error/page-3.vue
Normal file
@@ -0,0 +1,162 @@
|
||||
<script setup lang="ts">
|
||||
useHead({
|
||||
title: 'Error Page 3 - Vuero',
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="error-container">
|
||||
<div class="error-nav">
|
||||
<VDarkmodeToggle />
|
||||
</div>
|
||||
|
||||
<div class="error-wrapper">
|
||||
<div class="error-inner has-text-centered">
|
||||
<img
|
||||
class="light-image"
|
||||
src="/images/illustrations/placeholders/error-3.svg"
|
||||
alt=""
|
||||
>
|
||||
<img
|
||||
class="dark-image"
|
||||
src="/images/illustrations/placeholders/error-3-dark.svg"
|
||||
alt=""
|
||||
>
|
||||
<h3 class="dark-inverted">
|
||||
We couldn't find that page
|
||||
</h3>
|
||||
<p>
|
||||
Looks like we couldn't find that page. Please try again or contact an
|
||||
administrator if the problem persists.
|
||||
</p>
|
||||
<div class="button-wrap">
|
||||
<VButton
|
||||
color="primary"
|
||||
elevated
|
||||
rounded
|
||||
@click="() => router.go(-1)"
|
||||
>
|
||||
Take me Back
|
||||
</VButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.error-container {
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
|
||||
.error-nav {
|
||||
.dark-mode {
|
||||
position: absolute;
|
||||
inset-inline-end: 0;
|
||||
top: 0;
|
||||
display: inline-block;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.error-wrapper {
|
||||
max-width: 840px;
|
||||
margin: 0 auto;
|
||||
padding-top: 40px;
|
||||
|
||||
.error-inner {
|
||||
position: relative;
|
||||
max-width: 540px;
|
||||
margin: 0 auto;
|
||||
|
||||
.bg-number {
|
||||
font-family: var(--font);
|
||||
position: absolute;
|
||||
top: -58px;
|
||||
inset-inline-start: -50px;
|
||||
inset-inline-end: 0;
|
||||
margin: 0 auto;
|
||||
font-size: 28rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.15;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
img,
|
||||
svg,
|
||||
h3,
|
||||
p,
|
||||
.button-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5rem;
|
||||
font-family: var(--font-alt);
|
||||
color: var(--dark-text);
|
||||
font-weight: 600;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: var(--font);
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
.button {
|
||||
min-width: 220px;
|
||||
min-height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-dark {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
.error-inner {
|
||||
.bg-number {
|
||||
opacity: 0.09;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (width <= 767px) {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
padding-top: 60px;
|
||||
|
||||
.error-inner {
|
||||
padding: 10px;
|
||||
|
||||
.bg-number {
|
||||
top: -35px;
|
||||
inset-inline-start: -18px;
|
||||
inset-inline-end: 0;
|
||||
font-size: 13rem;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
max-width: 345px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
162
src/pages/error/page-4.vue
Normal file
162
src/pages/error/page-4.vue
Normal file
@@ -0,0 +1,162 @@
|
||||
<script setup lang="ts">
|
||||
useHead({
|
||||
title: 'Error Page 4 - Vuero',
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="error-container">
|
||||
<div class="error-nav">
|
||||
<VDarkmodeToggle />
|
||||
</div>
|
||||
|
||||
<div class="error-wrapper">
|
||||
<div class="error-inner has-text-centered">
|
||||
<img
|
||||
class="light-image"
|
||||
src="/images/illustrations/placeholders/error-4.svg"
|
||||
alt=""
|
||||
>
|
||||
<img
|
||||
class="dark-image"
|
||||
src="/images/illustrations/placeholders/error-4-dark.svg"
|
||||
alt=""
|
||||
>
|
||||
<h3 class="dark-inverted">
|
||||
We couldn't find that page
|
||||
</h3>
|
||||
<p>
|
||||
Looks like we couldn't find that page. Please try again or contact an
|
||||
administrator if the problem persists.
|
||||
</p>
|
||||
<div class="button-wrap">
|
||||
<VButton
|
||||
color="primary"
|
||||
elevated
|
||||
rounded
|
||||
@click="() => router.go(-1)"
|
||||
>
|
||||
Take me Back
|
||||
</VButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.error-container {
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
|
||||
.error-nav {
|
||||
.dark-mode {
|
||||
position: absolute;
|
||||
inset-inline-end: 0;
|
||||
top: 0;
|
||||
display: inline-block;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.error-wrapper {
|
||||
max-width: 840px;
|
||||
margin: 0 auto;
|
||||
padding-top: 40px;
|
||||
|
||||
.error-inner {
|
||||
position: relative;
|
||||
max-width: 540px;
|
||||
margin: 0 auto;
|
||||
|
||||
.bg-number {
|
||||
font-family: var(--font);
|
||||
position: absolute;
|
||||
top: -58px;
|
||||
inset-inline-start: -50px;
|
||||
inset-inline-end: 0;
|
||||
margin: 0 auto;
|
||||
font-size: 28rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.15;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
img,
|
||||
svg,
|
||||
h3,
|
||||
p,
|
||||
.button-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5rem;
|
||||
font-family: var(--font-alt);
|
||||
color: var(--dark-text);
|
||||
font-weight: 600;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: var(--font);
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
.button {
|
||||
min-width: 220px;
|
||||
min-height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-dark {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
.error-inner {
|
||||
.bg-number {
|
||||
opacity: 0.09;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (width <= 767px) {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
padding-top: 60px;
|
||||
|
||||
.error-inner {
|
||||
padding: 10px;
|
||||
|
||||
.bg-number {
|
||||
top: -35px;
|
||||
inset-inline-start: -18px;
|
||||
inset-inline-end: 0;
|
||||
font-size: 13rem;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
max-width: 345px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
165
src/pages/error/page-5.vue
Normal file
165
src/pages/error/page-5.vue
Normal file
@@ -0,0 +1,165 @@
|
||||
<script setup lang="ts">
|
||||
useHead({
|
||||
title: 'Error Page 5 - Vuero',
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="error-container">
|
||||
<div class="error-nav">
|
||||
<VDarkmodeToggle />
|
||||
</div>
|
||||
|
||||
<div class="error-wrapper">
|
||||
<div class="error-inner has-text-centered">
|
||||
<div class="bg-number dark-inverted">
|
||||
500
|
||||
</div>
|
||||
<img
|
||||
class="light-image"
|
||||
src="/images/illustrations/placeholders/error-5.svg"
|
||||
alt=""
|
||||
>
|
||||
<img
|
||||
class="dark-image"
|
||||
src="/images/illustrations/placeholders/error-5-dark.svg"
|
||||
alt=""
|
||||
>
|
||||
<h3 class="dark-inverted">
|
||||
Internal Server Error
|
||||
</h3>
|
||||
<p>
|
||||
Looks like an unexpacted problem occured. Please try again or contact the
|
||||
website administrator.
|
||||
</p>
|
||||
<div class="button-wrap">
|
||||
<VButton
|
||||
color="primary"
|
||||
elevated
|
||||
rounded
|
||||
@click="() => router.go(-1)"
|
||||
>
|
||||
Take me Back
|
||||
</VButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.error-container {
|
||||
width: 100vw;
|
||||
min-height: 100vh;
|
||||
|
||||
.error-nav {
|
||||
.dark-mode {
|
||||
position: absolute;
|
||||
inset-inline-end: 0;
|
||||
top: 0;
|
||||
display: inline-block;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.error-wrapper {
|
||||
max-width: 840px;
|
||||
margin: 0 auto;
|
||||
padding-top: 40px;
|
||||
|
||||
.error-inner {
|
||||
position: relative;
|
||||
max-width: 540px;
|
||||
margin: 0 auto;
|
||||
|
||||
.bg-number {
|
||||
font-family: var(--font);
|
||||
position: absolute;
|
||||
top: -58px;
|
||||
inset-inline-start: -50px;
|
||||
inset-inline-end: 0;
|
||||
margin: 0 auto;
|
||||
font-size: 28rem;
|
||||
font-weight: 600;
|
||||
opacity: 0.15;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
img,
|
||||
svg,
|
||||
h3,
|
||||
p,
|
||||
.button-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5rem;
|
||||
font-family: var(--font-alt);
|
||||
color: var(--dark-text);
|
||||
font-weight: 600;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: var(--font);
|
||||
font-size: 1.1rem;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.button-wrap {
|
||||
.button {
|
||||
min-width: 220px;
|
||||
min-height: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-dark {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
.error-inner {
|
||||
.bg-number {
|
||||
opacity: 0.09;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (width <= 767px) {
|
||||
.error-container {
|
||||
.error-wrapper {
|
||||
padding-top: 60px;
|
||||
|
||||
.error-inner {
|
||||
padding: 10px;
|
||||
|
||||
.bg-number {
|
||||
top: -35px;
|
||||
inset-inline-start: -18px;
|
||||
inset-inline-end: 0;
|
||||
font-size: 13rem;
|
||||
}
|
||||
|
||||
img,
|
||||
.iconify {
|
||||
max-width: 345px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
71
src/pages/index.vue
Normal file
71
src/pages/index.vue
Normal file
@@ -0,0 +1,71 @@
|
||||
<script setup lang="ts">
|
||||
import Layout from '/@src/layouts/landing.vue'
|
||||
import packageJson from '../../package.json'
|
||||
|
||||
useHead({
|
||||
title: '소액계약관리',
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Layout>
|
||||
<div class="hero is-fullheight is-active">
|
||||
<div class="hero-body has-text-centered">
|
||||
<div class="container">
|
||||
<h1 class="title is-1 is-bold dark-white is-leading">
|
||||
Build fast & beautiful web apps with <span>Vuero</span>
|
||||
</h1>
|
||||
<h3 class="subtitle is-4">
|
||||
Premium Vue Dashboard & Webapp UI Kit
|
||||
<span class="tag is-primary is-rounded">{{ packageJson.version }}</span>
|
||||
</h3>
|
||||
|
||||
<div class="buttons mb-2">
|
||||
<VButton
|
||||
href="https://go.cssninja.io/buy-vuero"
|
||||
color="primary"
|
||||
rounded
|
||||
>
|
||||
Buy Vuero Today
|
||||
</VButton>
|
||||
</div>
|
||||
|
||||
<div class="trusted-by mb-4">
|
||||
<span>Trusted by <span>2000+ customers</span></span>
|
||||
<div class="rating">
|
||||
<VIcon icon="uiw:star-on" />
|
||||
<VIcon icon="uiw:star-on" />
|
||||
<VIcon icon="uiw:star-on" />
|
||||
<VIcon icon="uiw:star-on" />
|
||||
<VIcon icon="uiw:star-on" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hero-mockup-wrap">
|
||||
<div class="hero-mockup">
|
||||
<img
|
||||
class="light-image-block"
|
||||
src="/images/illustrations/landing/app-1.webp"
|
||||
alt=""
|
||||
>
|
||||
<img
|
||||
class="dark-image-block"
|
||||
src="/images/illustrations/landing/app-1-dark.webp"
|
||||
alt=""
|
||||
>
|
||||
</div>
|
||||
<div class="hero-mockup-gradient" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
#vuero-demos,
|
||||
#vuero-components {
|
||||
scroll-margin-top: 50px;
|
||||
}
|
||||
</style>
|
||||
3
src/pages/navbar.vue
Normal file
3
src/pages/navbar.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<RouterView />
|
||||
</template>
|
||||
33
src/pages/navbar/dashboards.vue
Normal file
33
src/pages/navbar/dashboards.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
requiresAuth: true
|
||||
</route>
|
||||
|
||||
<script setup lang="ts">
|
||||
const layoutSwitcher = useLayoutSwitcher()
|
||||
const pageTitle = useVueroContext<string>('page-title')
|
||||
onMounted(() => {
|
||||
pageTitle.value = '메인'
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: '소액계약관리 - 메인',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="(layoutSwitcher.dynamicLayoutComponent as any)"
|
||||
v-bind="layoutSwitcher.dynamicLayoutProps"
|
||||
>
|
||||
<!-- Content Wrapper -->
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition
|
||||
name="fade-fast"
|
||||
mode="out-in"
|
||||
>
|
||||
<component :is="Component" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
</component>
|
||||
</template>
|
||||
6
src/pages/navbar/dashboards/index.vue
Normal file
6
src/pages/navbar/dashboards/index.vue
Normal file
@@ -0,0 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dashboard />
|
||||
</template>
|
||||
12
src/pages/navbar/index.vue
Normal file
12
src/pages/navbar/index.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
const router = useRouter()
|
||||
|
||||
onMounted(() => {
|
||||
router.push('/navbar/dashboards')
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div />
|
||||
</template>
|
||||
25
src/pages/navbar/layouts.vue
Normal file
25
src/pages/navbar/layouts.vue
Normal file
@@ -0,0 +1,25 @@
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
requiresAuth: true
|
||||
</route>
|
||||
|
||||
<script setup lang="ts">
|
||||
const layoutSwitcher = useLayoutSwitcher()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="(layoutSwitcher.dynamicLayoutComponent as any)"
|
||||
v-bind="layoutSwitcher.dynamicLayoutProps"
|
||||
>
|
||||
<!-- Content Wrapper -->
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition
|
||||
name="translate-page-x"
|
||||
mode="out-in"
|
||||
>
|
||||
<component :is="Component" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
</component>
|
||||
</template>
|
||||
40
src/pages/navbar/layouts/approval.vue
Normal file
40
src/pages/navbar/layouts/approval.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
requiresAuth: true
|
||||
</route>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Person } from '/@src/utils/types'
|
||||
|
||||
const pageTitle = useVueroContext<string>('page-title')
|
||||
const approval = ref(null)
|
||||
onMounted(() => {
|
||||
pageTitle.value = '신청내역'
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: '소액계약관리 - 신청내역',
|
||||
})
|
||||
|
||||
const apprLine = ref<any>({})
|
||||
|
||||
const onClick = () => {
|
||||
console.log(apprLine)
|
||||
}
|
||||
|
||||
const onCreateTab = (kind: string) => {
|
||||
approval.value?.appendTab(kind)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="page-content is-relative tabs-wrapper is-slider is-squared is-inverted is-navbar-lg"
|
||||
>
|
||||
<VApproval ref="approval" v-model="apprLine"/>
|
||||
|
||||
<VButton @click.prevent="onCreateTab('collabo')" color="primary">협조</VButton>
|
||||
<VButton @click.prevent="onCreateTab('control')" color="dark">통제</VButton>
|
||||
<VButton @click.prevent="onClick">클릭</VButton>
|
||||
</div>
|
||||
</template>
|
||||
24
src/pages/navbar/layouts/contract-list.vue
Normal file
24
src/pages/navbar/layouts/contract-list.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
requiresAuth: true
|
||||
</route>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
const pageTitle = useVueroContext<string>('page-title')
|
||||
onMounted(() => {
|
||||
pageTitle.value = '입찰신청'
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: '소액계약관리 - 입찰신청',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="page-content is-relative tabs-wrapper is-slider is-squared is-inverted is-navbar-lg"
|
||||
>
|
||||
<Contract />
|
||||
</div>
|
||||
</template>
|
||||
24
src/pages/navbar/layouts/est-list.vue
Normal file
24
src/pages/navbar/layouts/est-list.vue
Normal file
@@ -0,0 +1,24 @@
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
requiresAuth: true
|
||||
</route>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
const pageTitle = useVueroContext<string>('page-title')
|
||||
onMounted(() => {
|
||||
pageTitle.value = '입찰내역'
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: '소액계약관리 - 입찰내역',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="page-content is-relative tabs-wrapper is-slider is-squared is-inverted is-navbar-lg"
|
||||
>
|
||||
<Estimate />
|
||||
</div>
|
||||
</template>
|
||||
3
src/pages/sidebar.vue
Normal file
3
src/pages/sidebar.vue
Normal file
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<RouterView />
|
||||
</template>
|
||||
27
src/pages/sidebar/dashboards.vue
Normal file
27
src/pages/sidebar/dashboards.vue
Normal file
@@ -0,0 +1,27 @@
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
requiresAuth: true
|
||||
</route>
|
||||
|
||||
<script setup lang="ts">
|
||||
const layoutSwitcher = useLayoutSwitcher()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="(layoutSwitcher.dynamicLayoutComponent as any)"
|
||||
v-bind="layoutSwitcher.dynamicLayoutProps"
|
||||
close-on-change
|
||||
default-sidebar="dashboard"
|
||||
>
|
||||
<!-- Content Wrapper -->
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition
|
||||
name="fade-fast"
|
||||
mode="out-in"
|
||||
>
|
||||
<component :is="Component" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
</component>
|
||||
</template>
|
||||
12
src/pages/sidebar/dashboards/index.vue
Normal file
12
src/pages/sidebar/dashboards/index.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
const pageTitle = useVueroContext<string>('page-title')
|
||||
onMounted(() => {
|
||||
pageTitle.value = '메인'
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dashboard />
|
||||
</template>
|
||||
11
src/pages/sidebar/index.vue
Normal file
11
src/pages/sidebar/index.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
const router = useRouter()
|
||||
|
||||
onMounted(() => {
|
||||
router.push('/sidebar/dashboards')
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div />
|
||||
</template>
|
||||
22
src/pages/sidebar/layouts.vue
Normal file
22
src/pages/sidebar/layouts.vue
Normal file
@@ -0,0 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
const layoutSwitcher = useLayoutSwitcher()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="(layoutSwitcher.dynamicLayoutComponent as any)"
|
||||
v-bind="layoutSwitcher.dynamicLayoutProps"
|
||||
close-on-change
|
||||
default-sidebar="layout"
|
||||
>
|
||||
<!-- Content Wrapper -->
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition
|
||||
name="translate-page-x"
|
||||
mode="out-in"
|
||||
>
|
||||
<component :is="Component" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
</component>
|
||||
</template>
|
||||
28
src/pages/sidebar/layouts/approval.vue
Normal file
28
src/pages/sidebar/layouts/approval.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { Person } from '/@src/utils/types'
|
||||
|
||||
const pageTitle = useVueroContext<string>('page-title')
|
||||
onMounted(() => {
|
||||
pageTitle.value = '신청내역'
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: '소액계약관리 - 신청내역',
|
||||
})
|
||||
|
||||
const apprLine = ref<Person[]>([])
|
||||
|
||||
const onClick = () => {
|
||||
console.log(apprLine.value[0].sabun)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="page-content is-relative tabs-wrapper is-slider is-squared is-inverted is-navbar-lg"
|
||||
>
|
||||
<!-- default: 일반결재, (코스트 센터 기준 운영부서) control : 통제, (코스트 센터 기준 운영부서) collabo : 협조 -->
|
||||
<VApproval v-model="apprLine" apprMode="control"/>
|
||||
<VButton @click.prevent="onClick">클릭</VButton>
|
||||
</div>
|
||||
</template>
|
||||
19
src/pages/sidebar/layouts/contract-list.vue
Normal file
19
src/pages/sidebar/layouts/contract-list.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
const pageTitle = useVueroContext<string>('page-title')
|
||||
onMounted(() => {
|
||||
pageTitle.value = '가격조사'
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: '소액계약관리 - 가격조사',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="page-content is-relative tabs-wrapper is-slider is-squared is-inverted is-navbar-lg"
|
||||
>
|
||||
<Contract />
|
||||
</div>
|
||||
</template>
|
||||
19
src/pages/sidebar/layouts/est-list.vue
Normal file
19
src/pages/sidebar/layouts/est-list.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
const pageTitle = useVueroContext<string>('page-title')
|
||||
onMounted(() => {
|
||||
pageTitle.value = '신청내역'
|
||||
})
|
||||
|
||||
useHead({
|
||||
title: '소액계약관리 - 신청내역',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="page-content is-relative tabs-wrapper is-slider is-squared is-inverted is-navbar-lg"
|
||||
>
|
||||
<Estimate />
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user