initial commit

This commit is contained in:
Nadar 2024-03-06 16:23:48 +03:00
parent 902ec501b0
commit d33be0643b
17 changed files with 267 additions and 608 deletions

113
package-lock.json generated
View File

@ -8,10 +8,10 @@
"name": "test-task-medods",
"version": "0.0.0",
"dependencies": {
"@vuelidate/core": "^2.0.3",
"@vuelidate/validators": "^2.0.4",
"@yandex/ymaps3-types": "^0.0.21",
"vue": "^3.4.19",
"vue-router": "^4.3.0"
"vue-router": "^4.3.0",
"vue-yandex-maps": "^2.0.1"
},
"devDependencies": {
"@antfu/eslint-config": "^2.6.4",
@ -1508,86 +1508,23 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.19.tgz",
"integrity": "sha512-/KliRRHMF6LoiThEy+4c1Z4KB/gbPrGjWwJR+crg2otgrf/egKzRaCPvJ51S5oetgsgXLfc4Rm5ZgrKHZrtMSw=="
},
"node_modules/@vuelidate/core": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@vuelidate/core/-/core-2.0.3.tgz",
"integrity": "sha512-AN6l7KF7+mEfyWG0doT96z+47ljwPpZfi9/JrNMkOGLFv27XVZvKzRLXlmDPQjPl/wOB1GNnHuc54jlCLRNqGA==",
"dependencies": {
"vue-demi": "^0.13.11"
},
"node_modules/@yandex/ymaps3-types": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/@yandex/ymaps3-types/-/ymaps3-types-0.0.21.tgz",
"integrity": "sha512-mMKDhzHdV+4ZkzrN2oKzRXEHfCtS3/PLjzWUG2Tp5qsBWszViruk4gng+c/ORthztooYRgqB2+U5syNHDPc0Kw==",
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^2.0.0 || >=3.0.0"
"@types/react": "16-18",
"@types/react-dom": "16-18",
"@vue/runtime-core": "3"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@vuelidate/core/node_modules/vue-demi": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@vuelidate/validators": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@vuelidate/validators/-/validators-2.0.4.tgz",
"integrity": "sha512-odTxtUZ2JpwwiQ10t0QWYJkkYrfd0SyFYhdHH44QQ1jDatlZgTh/KRzrWVmn/ib9Gq7H4hFD4e8ahoo5YlUlDw==",
"dependencies": {
"vue-demi": "^0.13.11"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^2.0.0 || >=3.0.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@vuelidate/validators/node_modules/vue-demi": {
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz",
"integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"@vue/runtime-core": {
"optional": true
}
}
@ -4950,6 +4887,30 @@
"vue": "^3.2.0"
}
},
"node_modules/vue-yandex-maps": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/vue-yandex-maps/-/vue-yandex-maps-2.0.1.tgz",
"integrity": "sha512-tLP+3YZKazLNWsoYF2tMZCM4RCAUMspz5FOk2VnlPWaDFHi71PtHo8dfhTlf5Guy9YP2i11YjZGJfBfSUsEU4g==",
"dependencies": {
"@yandex/ymaps3-types": ">=0.0.21"
},
"engines": {
"node": ">=18"
},
"peerDependencies": {
"@vue/composition-api": ">=1",
"nuxt": "^2.16 || ^3",
"vue": "^2.7 || ^3.3"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"nuxt": {
"optional": true
}
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -1,18 +1,20 @@
{
"name": "test-task-medods",
"private": true,
"version": "0.0.0",
"type": "module",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
"preview": "vite preview",
"lint": "eslint .",
"lint:fix": "eslint . --fix"
},
"dependencies": {
"@vuelidate/core": "^2.0.3",
"@vuelidate/validators": "^2.0.4",
"@yandex/ymaps3-types": "^0.0.21",
"vue": "^3.4.19",
"vue-router": "^4.3.0"
"vue-router": "^4.3.0",
"vue-yandex-maps": "^2.0.1"
},
"devDependencies": {
"@antfu/eslint-config": "^2.6.4",

BIN
public/shop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 KiB

View File

@ -51,7 +51,6 @@ body {
body {
background: black;
font-family: "Montserrat", sans-serif;
overflow: hidden;
color: white;
}
@ -77,7 +76,7 @@ button:hover {
}
.container {
max-width: 800px;
max-width: 1400px;
width: 100%;
margin-inline: auto;
}

View File

@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["fonts.scss","style.scss","normalize.scss"],"names":[],"mappings":"AAAQ;AAER;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AC3CF;AAAA;EAEE;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EAEA;;;ACtCF;AAEA;AAAA;AAGA;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAUA;AAAA;AAGA;AAAA;AAAA;AAAA;AAKA;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;AAIA;AAAA;EAEE;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;AAAA;EAGE;EACA;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;EAEE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAAA;AAKA;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;EACA;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA,QACQ;EACN;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA,SACS;EACP;;;AAGF;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAIE;EACA;;;AAGF;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;EAEE;EACA;;;AAGF;AAAA;AAAA;AAIA;AAAA;EAEE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE","file":"index.css"}
{"version":3,"sourceRoot":"","sources":["fonts.scss","style.scss","normalize.scss"],"names":[],"mappings":"AAAQ;AAER;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AC3CF;AAAA;EAEE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EAEA;;;ACrCF;AAEA;AAAA;AAGA;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAUA;AAAA;AAGA;AAAA;AAAA;AAAA;AAKA;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;EACA;;;AAGF;AAAA;AAAA;AAIA;AAAA;EAEE;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;AAAA;EAGE;EACA;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;EAEE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAAA;AAKA;AAAA;AAAA;AAAA;AAAA;AAAA;EAME;EACA;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA,QACQ;EACN;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA,SACS;EACP;;;AAGF;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAIE;EACA;;;AAGF;AAAA;AAAA;AAIA;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;AAAA;EAEE;EACA;;;AAGF;AAAA;AAAA;AAIA;AAAA;EAEE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAAA;AAKA;EACE;EACA;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAGA;AAAA;AAAA;AAIA;EACE;;;AAGF;AAAA;AAAA;AAIA;EACE","file":"index.css"}

View File

@ -6,7 +6,6 @@ body {
body {
background: black;
font-family: 'Montserrat', sans-serif;
overflow: hidden;
color: white;
}
@ -33,7 +32,7 @@ button {
}
.container{
max-width: 800px;
max-width: 1400px;
width: 100%;
margin-inline: auto;

View File

@ -1,58 +0,0 @@
<template>
<button
class="btn" :class="[{ btn_icon: icon }, { btn_medium: medium }]"
@click="clickOnButton()"
>
<slot v-if="icon" name="icon">
<Component :is="icon" />
</slot>
<slot v-if="!icon" />
</button>
</template>
<script setup>
defineProps({
icon: {},
medium: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['click'])
function clickOnButton() {
emit('click')
}
</script>
<style lang="scss" scoped>
.btn {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
background: white;
color: black;
border: none;
cursor: pointer;
font-size: 14px;
transition: .2s;
&_icon {
padding: 10px;
background-color: #F4F5FD;
border-radius: 8px;
width: 44px;
height: 44px;
}
&_medium {
width: 140px;
height: 42px;
background-color: #FFE27A;
border-radius: 7px;
}
}
</style>

View File

@ -1,87 +0,0 @@
<template>
<div>
<input
class='checkbox'
type="checkbox"
:id="id"
:checked="checked"
@input="handleClick($event)">
<label :for="id">{{ text }}</label>
</div>
</template>
<script setup>
const emits = defineEmits(['update:checked'])
const props = defineProps({
checked: {
type: Boolean,
default: false
},
id: {
type: String,
default: ''
},
text: {
type: String,
default: ''
},
})
const handleClick = (event) => {
emits('update:checked', event.target.checked)
}
</script>
<style lang="scss" scoped>
.checkbox {
position: absolute;
z-index: -1;
opacity: 0;
& + label {
display: inline-flex;
align-items: center;
user-select: none;
}
& + label::before {
content: '';
display: inline-block;
width: 24px;
height: 24px;
flex-shrink: 0;
flex-grow: 0;
border: 1px solid #adb5bd;
border-radius: 6px;
margin-right: 10px;
background-repeat: no-repeat;
background-position: center center;
background-size: 50% 50%;
}
&:checked + label::before {
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e");
}
&:not(:disabled):not(:checked) + label:hover::before {
border-color: var(--primary-hover);
}
&:not(:disabled):active + label::before {
background-color: var(--primary);
border: 1px solid #ECEBED;
}
&:focus + label::before {
box-shadow: 0 7px 20px rgba(0, 0, 0, 0.07);
}
&:focus:not(:checked) + label::before {
border-color: var(--primary);
}
&:disabled + label::before {
background-color: #e9ecef;
border: 1px solid #ECEBED;
}
}
</style>

View File

@ -1,84 +0,0 @@
<template>
<label
class="app-input"
:style="{width: width}"
>
<div class="app-input__title">{{ title }}</div>
<input
:placeholder=placeholder
:value="value"
@input="updateValue"
>
<div
class="app-input__warning"
v-for="element of error"
:key="element.$uid">
<div class="form-error__message">{{ element.$message }}</div>
</div>
</label>
</template>
<script setup>
const emit = defineEmits(['update:value'])
const props = defineProps({
error: {
type: Array,
default: ''
},
value: {
type: String,
default: ''
},
width: {
type: String,
default: '300px'
},
title: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
warning: {
type: String,
default: ''
}
})
const updateValue = (e) => {
emit('update:value', e.target.value)
}
</script>
<style lang="scss" scoped>
.app-input {
border-radius: 10px;
cursor: pointer;
&:hover {
opacity: 0.7;
}
input {
width: 100%;
border-radius: 5px;
padding: 10px;
height: 25px;
}
&__title {
margin-bottom: 5px;
}
&__warning {
color: red;
margin-top: 5px;
input {
color: red;
}
}
}
</style>

View File

@ -1,41 +0,0 @@
<template>
<label class="app-select">
<div>{{ title }}</div>
<select class="select">
<option v-for="item in items" :key="item.id">
{{ item }}
</option>
</select>
</label>
</template>
<script setup>
defineProps({
items: {
type: Array,
required: true
},
title: {
type: String,
default: ''
}
})
</script>
<style lang="scss">
.app-select {
width: 300px;
cursor: pointer;
&:hover {
opacity: 0.7;
}
}
.select {
padding: 10px;
width: 100%;
height: 45px;
border-radius: 5px;
}
</style>

View File

@ -0,0 +1,107 @@
<template>
<YandexMap
:settings="{ ...mapParameters, theme }"
width="1270px"
height="500px"
>
<YandexMapCartesianProjection
:bounds="[
[-PIC_WIDTH / 2, PIC_HEIGHT / 2 - worldSize],
[worldSize - PIC_WIDTH / 2, PIC_HEIGHT / 2],
]"
/>
<YandexMapTileDataSource :settings="dataSourceProps" />
<YandexMapLayer :settings="layerProps" />
<YandexMapDefaultFeaturesLayer />
<YandexMapDefaultMarker :settings="{ coordinates: [0, 0] }" />
<YandexMapDefaultMarker :settings="{ coordinates: [600, 0] }" />
<YandexMapDefaultMarker :settings="{ coordinates: [0, 600] }" />
</YandexMap>
</template>
<script setup lang="ts">
import {
YandexMap,
YandexMapCartesianProjection,
YandexMapDefaultFeaturesLayer,
YandexMapDefaultMarker,
YandexMapLayer,
YandexMapTileDataSource,
} from 'vue-yandex-maps'
import type {
LngLatBounds,
YMapLayerProps,
YMapTileDataSourceProps,
} from '@yandex/ymaps3-types'
const theme = 'black'
const TILES_PATH = 'https://yastatic.net/s3/front-maps-static/maps-front-jsapi-3/examples/images/custom-map/tiles'
/* To calculate the coordinates of the lower left and upper right corners of a rectangular coordinate
* area, we need to know the maximum zoom, width and height of the image in pixels at maximum zoom.
*/
const MAX_ZOOM = 4
const MIN_ZOOM = 3
const PIC_WIDTH = 2526
const PIC_HEIGHT = 1642
const dataSourceProps: YMapTileDataSourceProps = {
id: 'custom',
raster: {
type: 'ground',
/*
fetchTile is called to get data for displaying a custom tile
This method can be of several variants:
1) x y z placeholders for tile coordinates
2) method that returns final url
3) method that fetches tile manually
In this example, we use option 1
*/
fetchTile: `${TILES_PATH}/{{z}}/tile-{{x}}-{{y}}.jpg`,
},
zoomRange: { min: MIN_ZOOM, max: MAX_ZOOM },
clampMapZoom: true,
}
/*
A text identifier is used to link the data source and the layer.
Be careful, the identifier for the data source is set in the id field,
and the source field is used when transferring to the layer
*/
const layerProps: YMapLayerProps = {
id: 'customLayer',
source: 'custom',
type: 'ground',
options: {
raster: {
awaitAllTilesOnFirstDisplay: true,
},
},
}
// Calculate the size of all tiles at the maximum zoom.
const worldSize = 2 ** MAX_ZOOM * 256
// Limiting the scrolling area of our map to the size of the entire image
const RESTRICT_AREA: LngLatBounds = [
[-PIC_WIDTH / 2, -PIC_HEIGHT / 2],
[PIC_WIDTH / 2, PIC_HEIGHT / 2],
]
const mapParameters: {
mode: string
worldOptions: { cycledY: boolean, cycledX: boolean }
location: { center: [number, number], zoom: number }
restrictMapArea: [[lon: number, lat: number, alt: number | undefined], [lon: number, lat: number, alt: number | undefined]]
} = {
location: { center: [0, 0], zoom: MAX_ZOOM },
mode: 'raster',
restrictMapArea: RESTRICT_AREA,
// Do not copy the world along the axes
// @ts-expect-error Яндекс забыли про cycledY в типах
worldOptions: { cycledX: false, cycledY: false },
}
</script>

51
src/components/map.vue Normal file
View File

@ -0,0 +1,51 @@
<template>
<div class="map">
<YandexMap
v-model="map"
:settings="{
location: {
center: merkuriyCoordinates,
zoom: 16,
},
}"
width="1270px"
height="350px"
>
<YandexMapDefaultSchemeLayer />
<YandexMapDefaultFeaturesLayer />
<YandexMapMarker
:settings="{ coordinates: merkuriyCoordinates }"
>
<a href="https://yandex.ru/maps/-/CDFyiEYK" target="_blank">
<img
class="pin"
alt="#"
src="../../public/shop.png"
>
</a>
</YandexMapMarker>
</YandexMap>
</div>
</template>
<script setup>
import { YandexMap, YandexMapDefaultFeaturesLayer, YandexMapDefaultSchemeLayer, YandexMapMarker } from 'vue-yandex-maps'
const merkuriyCoordinates = [56.084516, 54.822215]
</script>
<style lang="scss" scoped>
.map {
max-width: 1200px;
}
.pin {
transform: translateX(-50%) translateY(-50%);
cursor: pointer;
max-width: unset;
width: 50px;
height: 50px;
border-radius: 50%;
}
</style>

View File

@ -1,11 +1,18 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from "./router/index.js"
import router from './router/index.js'
import './assets/index.scss'
// eslint-disable-next-line import/order
import { createYmaps } from 'vue-yandex-maps'
const app = createApp(App)
app
.use(router)
.use(createYmaps({
apikey: '13f4c06b-cb7e-4eeb-81f1-af52f12587b2',
importModules: ['@yandex/ymaps3-controls@0.0.1'],
}))
.mount('#app')

View File

@ -1,228 +0,0 @@
<template>
<div class="createUser">
<div class="container">
<h1 class="createUser__title">Создание пользователя</h1>
<form @submit.prevent="submitForm" class="createUser__form">
<h3>Персональные данные</h3>
<div class="createUser__row">
<AppInput
placeholder='Введите фамилию'
title="Фамилия"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
<AppInput
placeholder='Введите имя'
title="Имя"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
</div>
<div class="createUser__row">
<AppInput
placeholder='Введите отчество'
title="Отчество"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
<AppInput
placeholder='Введите дату рождения'
title="Дата рождения"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
</div>
<div class="createUser__row">
<AppSelect
title="Укажите ваш пол"
:items="['Мужской','Женский']"
/>
<AppSelect
title="Группа клиентов"
:items="['Vip','Проблемные','ОМС']"
/>
</div>
<div class="createUser__row">
<AppInput
placeholder='Введите номер телефона'
title="Номер телефона"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
<AppSelect
title="Лечющий врач"
:items="['Иванов', 'Захаров', 'Чернышева']"
/>
</div>
<div class="createUser__row">
<AppCheckbox
class="createUser__checkbox"
text="Не отправлять СМС"
id="checkboxIsActive"
v-model:checked="checkboxIsActive"/>
</div>
<h3>Адресс</h3>
<div class="createUser__row">
<AppInput
placeholder='Введите индекс'
title="Индекс"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
<AppInput
placeholder='Введите вашу страну'
title="Страна"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
</div>
<div class="createUser__row">
<AppInput
placeholder='Введите вагу область'
title="Область"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
<AppInput
placeholder='Введите ваш город'
title="Город"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
</div>
<div class="createUser__row">
<AppInput
placeholder='Введите вашу улицу'
title="Улица"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
<AppInput
placeholder='Введите ваш номер дома'
title="Дом"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
</div>
<h3>Паспортные данные</h3>
<div class="createUser__row">
<AppSelect
title='Выберите документ'
:items="['Паспорт','Свидетельство о рождении','Водительское удостоверение']"
/>
<AppInput
placeholder='Введите серию'
title="Серия"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
</div>
<div class="createUser__row">
<AppInput
placeholder='Введите номер'
title="Номер"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
<AppInput
placeholder='Дата'
title="Дата выдвчи"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
</div>
<div class="createUser__row">
<AppInput
width="100%"
placeholder='Введите название оргонизации'
title="Кем выдан"
v-model:value="v$.nameField.$model"
:error="v$.nameField.$errors"
/>
</div>
<AppButton medium type="Submit">Confirm</AppButton>
</form>
</div>
</div>
</template>
<script setup>
import AppButton from "../components/app-button.vue";
import AppInput from "../components/app-input.vue";
import {computed, ref} from "vue";
import {email, helpers, minLength} from "@vuelidate/validators";
import useVuelidate from "@vuelidate/core";
import AppCheckbox from "../components/app-checkbox.vue";
import AppSelect from "../components/app-select.vue";
const checkboxIsActive = ref(false)
const nameField = ref('')
const emailField = ref('')
const rules = computed(() => ({
nameField: {
required: true,
minLength: helpers.withMessage(`Минимальная длина: 6 символа`, minLength(6))
},
emailField: {
required: true,
email: helpers.withMessage('Вы ввели неверный email', email)
},
}))
const v$ = useVuelidate(rules, {nameField, emailField})
function submitForm() {
alert('pizda')
}
</script>
<style lang="scss">
.createUser {
height: 100%;
&__title {
margin-top: 30px;
margin-bottom: 50px;
}
&__form {
//display: flex;
flex-direction: column;
gap: 30px;
height: 100%;
@media (max-width: 700px) {
align-items: center;
}
}
&__row {
display: flex;
flex-direction: row;
justify-content: space-between;
@media (max-width: 700px) {
display: flex;
flex-direction: column;
gap: 30px;
}
}
&__checkbox {
margin-top: auto;
}
}
.inputblock {
display: flex;
flex-direction: column;
gap: 30px;
}
</style>

31
src/pages/map.vue Normal file
View File

@ -0,0 +1,31 @@
<template>
<div class="map-page">
<div class="container">
<h1>Карта</h1>
<Map />
<h1 class="custom">
Карта торгового центра
</h1>
<CustomMap />
</div>
</div>
</template>
<script setup>
import CustomMap from '../components/custom-map.vue'
import Map from '../components/map.vue'
</script>
<style scoped lang="scss">
.map-page {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.custom {
margin-top: 200px;
margin-block: auto;
}
</style>

View File

@ -1,10 +1,10 @@
import { createRouter, createWebHistory } from 'vue-router'
import Test from "../pages/createUser.vue";
import Map from '../pages/map.vue'
const routes = [
{
path: '/',
component: Test,
component: Map,
},
]