Skip to content

Commit d32d5af

Browse files
committed
form locations
1 parent 1766751 commit d32d5af

File tree

12 files changed

+287
-212
lines changed

12 files changed

+287
-212
lines changed

src/analytics/location.analytic.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
11
import analytics from '@/analytics/index'
2-
import { LocationType } from '@/models/types'
2+
import { ProjectLocationForm } from '@/models/location.model'
33

44
export interface LocationAnalytic {
55
project: {
66
id: string
77
}
8-
location: {
9-
lat: number
10-
lng: number
11-
type: LocationType
12-
}
8+
location: ProjectLocationForm
139
}
1410

1511
export default {

src/api/locations.services.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { LocationModel, LocationOutput } from '@/models/location.model'
1+
import type { LocationModel, ProjectLocationForm } from '@/models/location.model'
22
import utils from '@/functs/functions'
33
import useAPI from '@/composables/useAPI'
44

@@ -19,7 +19,7 @@ export async function getLocations(params, next) {
1919
return await useAPI(`location/`, { ...utils.adaptParam(params) }) //.data.value
2020
}
2121

22-
export async function postLocations(projectId: string, body: Omit<LocationOutput, 'id'>) {
22+
export async function postLocations(projectId: string, body: ProjectLocationForm) {
2323
return await useAPI<LocationModel>(`project/${projectId}/location/`, {
2424
body,
2525
method: 'POST',
@@ -29,7 +29,7 @@ export async function postLocations(projectId: string, body: Omit<LocationOutput
2929
export async function patchLocation(
3030
projectId: string,
3131
locationId: number,
32-
body: Partial<LocationOutput>
32+
body: ProjectLocationForm
3333
) {
3434
return await useAPI<LocationModel>(`project/${projectId}/location/${locationId}/`, {
3535
body,

src/components/base/form/TextInput.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,18 @@
4242
</span>
4343

4444
<small v-if="bottomText">{{ bottomText }}</small>
45+
46+
<FieldErrors :errors="errors" />
4547
</div>
4648
</template>
4749

4850
<script>
51+
import FieldErrors from '@/components/base/form/FieldErrors.vue'
4952
import IconImage from '@/components/base/media/IconImage.vue'
5053
export default {
5154
name: 'TextInput',
5255
53-
components: { IconImage },
56+
components: { IconImage, FieldErrors },
5457
5558
props: {
5659
autofocus: {
@@ -113,6 +116,10 @@ export default {
113116
type: [Number, String],
114117
default: 3,
115118
},
119+
errors: {
120+
type: Array,
121+
default: () => [],
122+
},
116123
},
117124
118125
emits: ['update:modelValue', 'enter', 'focus', 'blur'],
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<template>
2+
<DialogModal
3+
:confirm-button-label="isExist ? $t('common.edit') : $t('common.add')"
4+
:cancel-button-label="$t('common.cancel')"
5+
:asyncing="loading"
6+
:disabled="loading || !isValid"
7+
@close="$emit('close')"
8+
@submit="$emit('submit')"
9+
>
10+
<template #header>
11+
{{ isExist ? $t('location.edit-location-point') : $t('location.add-location-point') }}
12+
</template>
13+
14+
<template #body>
15+
<div class="location-type-ctn">
16+
<div class="location-type-label">
17+
{{ $t('location.location-type-label') }}
18+
</div>
19+
<GroupButton v-model="form.type" :options="locationTypeOptions" />
20+
</div>
21+
22+
<TextInput v-model="form.title" :errors="errors.title" :label="$t('common.title')" />
23+
24+
<TextInput
25+
v-model="form.description"
26+
:errors="errors.description"
27+
input-type="textarea"
28+
:label="$t('common.description')"
29+
class="description-input"
30+
/>
31+
</template>
32+
33+
<template v-if="isExist" #extra-buttons>
34+
<LpiButton
35+
class="delete-button"
36+
:label="$t('common.delete')"
37+
:btn-icon="loading ? 'LoaderSimple' : null"
38+
@click="$emit('delete')"
39+
/>
40+
</template>
41+
</DialogModal>
42+
</template>
43+
44+
<script setup lang="ts">
45+
import DialogModal from '@/components/base/modal/DialogModal.vue'
46+
import TextInput from '@/components/base/form/TextInput.vue'
47+
import GroupButton from '@/components/base/button/GroupButton.vue'
48+
import LpiButton from '@/components/base/button/LpiButton.vue'
49+
import { LocationForm } from '@/models/location.model'
50+
import { useLocationForm } from '@/form/location'
51+
52+
withDefaults(
53+
defineProps<{
54+
loading?: boolean
55+
}>(),
56+
{
57+
loading: false,
58+
}
59+
)
60+
defineEmits(['submit', 'close', 'delete'])
61+
const { t } = useNuxtI18n()
62+
63+
const model = defineModel<LocationForm>()
64+
const { form, isValid, errors } = useLocationForm({ model })
65+
const isExist = computed(() => !!form.value.id)
66+
67+
const locationTypeOptions = computed(() => [
68+
{
69+
value: 'team',
70+
label: t('location.team'),
71+
},
72+
{
73+
value: 'impact',
74+
label: t('location.impact'),
75+
},
76+
{
77+
value: 'address',
78+
label: t('location.address'),
79+
},
80+
])
81+
</script>
82+
83+
<style lang="scss" scoped>
84+
.new-coords {
85+
text-align: center;
86+
font-style: italic;
87+
font-weight: normal;
88+
}
89+
90+
.description-input {
91+
margin-top: $space-m;
92+
}
93+
94+
.location-type-ctn {
95+
margin: $space-m 0;
96+
97+
.location-type-label {
98+
font-size: $font-size-s;
99+
color: $primary-dark;
100+
font-weight: bold;
101+
margin-bottom: $space-2xs;
102+
}
103+
}
104+
105+
.delete-button {
106+
color: $white;
107+
background: $salmon;
108+
}
109+
</style>
Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
<template>
22
<div class="location-tooltip" :class="location.type">
3-
<div class="title">
4-
<div :class="location.type" />
5-
<span>{{ title }}</span>
3+
<div class="location-tooltip__header">
4+
<div :class="location.type" class="location-tooltip__header--dot" />
5+
<h2 class="location-tooltip__header--title">
6+
{{ typeLabel }}
7+
</h2>
68
</div>
79

8-
<p>{{ description }}</p>
10+
<div class="location-tooltip__location">
11+
<h3 class="location-tooltip__location--title">
12+
{{ title }}
13+
</h3>
14+
<p class="location-tooltip__location--description">
15+
{{ description }}
16+
</p>
17+
</div>
18+
<slot />
919
</div>
1020
</template>
1121

@@ -15,27 +25,46 @@ import { TranslatedLocation } from '@/models/location.model'
1525
1626
const props = defineProps<{ location: TranslatedLocation }>()
1727
28+
const { t } = useNuxtI18n()
29+
1830
const title = computed(() => cropIfTooLong(props.location?.$t?.title, 45))
1931
const description = computed(() => cropIfTooLong(props.location?.$t?.description, 85))
32+
33+
const typeLabel = computed(() => {
34+
switch (props.location.type) {
35+
case 'impact':
36+
return t('location.impact')
37+
case 'team':
38+
return t('location.team')
39+
case 'address':
40+
return t('location.address')
41+
}
42+
})
2043
</script>
2144

2245
<style lang="scss" scoped>
2346
.location-tooltip {
24-
min-width: 100px;
25-
padding: $space-m;
26-
27-
.title {
28-
color: $primary-dark;
29-
font-weight: 700;
30-
margin-bottom: $space-xs;
31-
font-size: $font-size-m;
47+
overflow: hidden;
48+
display: flex;
49+
width: 100%;
50+
height: 100%;
51+
transition: opacity 0.15s ease-in-out;
52+
flex-direction: column;
53+
54+
&__header {
3255
display: flex;
33-
align-items: center;
3456
justify-content: flex-start;
57+
padding: $space-s;
58+
59+
&--title {
60+
color: $primary-dark;
61+
font-weight: 700;
62+
font-size: $font-size-s;
63+
}
3564
36-
> div {
37-
height: 15px;
38-
width: 15px;
65+
&--dot {
66+
width: pxToRem(16px);
67+
height: pxToRem(16px);
3968
border-radius: 50%;
4069
margin-right: $space-s;
4170
@@ -52,5 +81,19 @@ const description = computed(() => cropIfTooLong(props.location?.$t?.description
5281
}
5382
}
5483
}
84+
85+
&__location {
86+
padding: $space-s;
87+
88+
&--title {
89+
font-weight: 500;
90+
font-size: $font-size-xl;
91+
}
92+
93+
&--description {
94+
font-weight: 400;
95+
font-size: $font-size-m;
96+
}
97+
}
5598
}
5699
</style>

0 commit comments

Comments
 (0)