Skip to content

Commit 237b595

Browse files
committed
fix: location input not rendering if missing data
1 parent 5890aea commit 237b595

File tree

7 files changed

+132
-80
lines changed

7 files changed

+132
-80
lines changed

packages/common-helpers/src/locale/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export const localeForm: tLocaleForm = {
108108
form_requires_n_values:
109109
"No values are required | A value is required | {count} values are required",
110110
form_loading_countries: "Loading countries...",
111+
form_awaiting_countries: "Awaiting countries data...",
111112
form_country: "Look for country",
112113
form_state: "Look for state",
113114
form_city: "Look for city",

packages/common-helpers/src/locale/es.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ export const localeForm: tLocaleForm = {
109109
form_requires_n_values:
110110
"No se requieren valores | Se requiere un valor | {count} valores son requeridos",
111111
form_loading_countries: "Cargando países...",
112+
form_awaiting_countries: "Esperando datos de países...",
112113
form_country: "Buscar país",
113114
form_state: "Buscar provincia",
114115
form_city: "Buscar ciudad",

packages/common-types/src/locale.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ export type tLocaleForm = {
152152
form_requires_n_values: string;
153153
/** @example "Loading countries..." */
154154
form_loading_countries: string;
155+
/** @example "Awaiting countries data..." */
156+
form_awaiting_countries: string;
155157
/** @example "Look for country" */
156158
form_country: string;
157159
/** @example "Look for state" */

packages/components-vue/src/components/form/Input.vue

Lines changed: 51 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@
125125
:key="indicativesArr.length"
126126
:content="!!indicativesArr.length"
127127
:model="models[i].value"
128+
:label="t('form_awaiting_countries')"
128129
:values="[2]"
129130
>
130131
<SelectSimple
@@ -147,54 +148,64 @@
147148
@update:model-value="updateArrModel(i, 1, $event)"
148149
/>
149150
</FormInputNValues>
150-
<FormInputCountriesAPI
151+
<FormInputNValues
151152
v-else-if="input.type === eFT.LOCATION"
152-
v-slot="{ statesReq, citiesReq }"
153-
v-bind="{ theme, states, countries, loading, errors, refresh }"
154-
:key="`${defaultCountry}-${countriesArr.length}-${statesArr?.length}`"
153+
v-bind="{ loading, errors, refresh }"
154+
:key="statesArr?.length"
155+
:content="!!countriesArr.length"
155156
:model="models[i].value"
157+
:label="t('form_awaiting_countries')"
158+
:values="[1, 3]"
156159
>
157-
<SelectFilter
158-
v-if="!defaultCountry || models[i].value.length === 1"
159-
:model-value="models[i].value[0]"
160-
:options="countriesArr"
161-
name="country"
162-
:value="defaultCountry"
163-
icon="earth-americas"
164-
:theme="theme"
165-
:disabled="readonly"
166-
:placeholder="getInputPlaceholder()"
167-
class="--width-180:md --flx"
168-
@update:model-value="updateArrModel(i, 0, $event)"
169-
/>
170-
<div
171-
v-if="models[i].value.length === 3"
172-
class="flx --flxRow-wrap --flx-start-stretch --gap-5 --flx"
160+
<!-- Single value means country, 3 values means country, state & city -->
161+
<FormInputCountriesAPI
162+
v-slot="{ statesReq, citiesReq }"
163+
v-bind="{ theme, states, countries, loading, errors, refresh }"
164+
:key="`${defaultCountry}-${countriesArr.length}-${statesArr?.length}`"
165+
:model="models[i].value"
173166
>
174167
<SelectFilter
175-
:model-value="models[i].value[1]"
176-
:options="statesArr || statesReq?.content?.map?.(stateToOption)"
177-
name="state"
178-
icon="mountain-sun"
168+
v-if="!defaultCountry || models[i].value.length === 1"
169+
:model-value="models[i].value[0]"
170+
:options="countriesArr"
171+
name="country"
172+
:value="defaultCountry"
173+
icon="earth-americas"
179174
:theme="theme"
180-
:disabled="readonly || !(models[i].value[0] || defaultCountry)"
181-
:placeholder="getInputPlaceholder(1)"
175+
:disabled="readonly"
176+
:placeholder="getInputPlaceholder()"
182177
class="--width-180:md --flx"
183-
@update:model-value="updateArrModel(i, 1, $event)"
178+
@update:model-value="updateArrModel(i, 0, $event)"
184179
/>
185-
<SelectFilter
186-
:model-value="models[i].value[2]"
187-
:options="citiesReq?.content?.map?.(cityToOption)"
188-
name="city"
189-
icon="city"
190-
:theme="theme"
191-
:disabled="readonly || !models[i].value[1]"
192-
:placeholder="getInputPlaceholder(2)"
193-
class="--width-180:md --flx"
194-
@update:model-value="updateArrModel(i, 2, $event)"
195-
/>
196-
</div>
197-
</FormInputCountriesAPI>
180+
<div
181+
v-if="models[i].value.length === 3"
182+
class="flx --flxRow-wrap --flx-start-stretch --gap-5 --flx"
183+
>
184+
<SelectFilter
185+
:model-value="models[i].value[1]"
186+
:options="statesArr || statesReq?.content?.map?.(stateToOption)"
187+
name="state"
188+
icon="mountain-sun"
189+
:theme="theme"
190+
:disabled="readonly || !(models[i].value[0] || defaultCountry)"
191+
:placeholder="getInputPlaceholder(1)"
192+
class="--width-180:md --flx"
193+
@update:model-value="updateArrModel(i, 1, $event)"
194+
/>
195+
<SelectFilter
196+
:model-value="models[i].value[2]"
197+
:options="citiesReq?.content?.map?.(cityToOption)"
198+
name="city"
199+
icon="city"
200+
:theme="theme"
201+
:disabled="readonly || !models[i].value[1]"
202+
:placeholder="getInputPlaceholder(2)"
203+
class="--width-180:md --flx"
204+
@update:model-value="updateArrModel(i, 2, $event)"
205+
/>
206+
</div>
207+
</FormInputCountriesAPI>
208+
</FormInputNValues>
198209
<FormInputNValues
199210
v-else-if="input.type === eFT.SCHEDULE"
200211
:model="models[i].value"

packages/components-vue/src/components/form/InputCountriesAPI.vue

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,36 @@
11
<template>
2-
<FormInputNValues
3-
:key="states?.length"
4-
v-bind="{ model, loading, errors, refresh }"
5-
:content="!!countries?.length"
6-
:values="[1, 3]"
2+
<BaseWrapper
3+
v-slot="statesReq"
4+
:wrapper="LoaderContentFetch"
5+
:wrap="!loading && !states?.length"
6+
:promise="getCountryStates"
7+
:url="`/${model[0]}?states`"
8+
:payload="[countryValue]"
9+
:fallback="[]"
10+
:theme="theme"
11+
unwrap
712
>
813
<BaseWrapper
9-
v-slot="statesReq"
14+
v-slot="citiesReq"
1015
:wrapper="LoaderContentFetch"
11-
:wrap="!loading && !states && !!countryValue"
12-
:theme="theme"
13-
:promise="getCountryStates"
14-
:url="`/${model[0]}?states`"
15-
:payload="[countryValue]"
16+
:wrap="!loading && !statesReq?.loading && !!model[1]"
17+
:promise="getStateCities"
18+
:url="`/${model[0]}/${model[1]}?cities`"
19+
:payload="[countryValue, model[1]]"
1620
:fallback="[]"
21+
:theme="theme"
1722
unwrap
1823
>
19-
<LoaderContentFetch
20-
v-slot="citiesReq"
21-
:theme="theme"
22-
:prevent-autoload="!model[1]"
23-
:no-loader="statesReq?.loading"
24-
:promise="getStateCities"
25-
:url="`/${model[0]}/${model[1]}?cities`"
26-
:payload="[countryValue, model[1]]"
27-
:fallback="[]"
28-
unwrap
29-
>
30-
<slot v-bind="{ statesReq, citiesReq }"></slot>
31-
</LoaderContentFetch>
24+
<slot v-bind="{ statesReq, citiesReq }"></slot>
3225
</BaseWrapper>
33-
</FormInputNValues>
26+
</BaseWrapper>
3427
</template>
3528

3629
<script setup lang="ts">
3730
import { computed } from "vue";
3831
3932
import BaseWrapper from "../base/Wrapper.vue";
4033
import LoaderContentFetch from "../loader/ContentFetch.vue";
41-
// input helper components
42-
import FormInputNValues from "./InputNValues.vue";
4334
4435
import type { iUseThemeProps } from "../../types/props";
4536
import type { iCountry, iState } from "../../types/countries";
@@ -49,6 +40,7 @@
4940
model: string[];
5041
countries?: iCountry[];
5142
states?: iState[];
43+
/** Loading countries and states */
5244
loading?: boolean;
5345
errors?: unknown;
5446
refresh?: (...args: any[]) => any;

packages/components-vue/src/components/form/InputNValues.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<LoaderContent
33
v-if="Array.isArray(model) && modelHasLength"
44
class="flx --flxRow-wrap --flx-start-stretch --gap-5 --flx"
5-
v-bind="{ loading, content, errors, refresh }"
5+
v-bind="{ loading, content, errors, refresh, label }"
66
>
77
<slot></slot>
88
</LoaderContent>
@@ -27,6 +27,8 @@
2727
content?: boolean;
2828
loading?: boolean;
2929
errors?: unknown;
30+
/** Loader label */
31+
label?: string;
3032
refresh?: (...args: any[]) => any;
3133
}
3234

packages/components-vue/src/components/form/Simple.stories.ts

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import type { Meta, StoryObj } from "@storybook/vue3";
22
import type { iInvalidInput, tFormInput } from "@open-xamu-co/ui-common-types";
3+
import { ref } from "vue";
34

4-
import { FormInput } from "@open-xamu-co/ui-common-helpers";
5+
import { FormInput, useForm } from "@open-xamu-co/ui-common-helpers";
56
import { eFormType } from "@open-xamu-co/ui-common-enums";
67

78
import FormSimple from "./Simple.vue";
8-
import { ref } from "vue";
9+
import ActionButton from "../action/Button.vue";
910

1011
const meta: Meta = {
1112
title: "Form/Form Simple",
@@ -88,16 +89,58 @@ export const WithInputs: Story = {
8889
};
8990

9091
export const WithLocationField: Story = {
91-
args: {
92-
modelValue: [
93-
new FormInput({
94-
values: [["CO", "VAC", "Cali"]],
95-
name: "location",
96-
type: eFormType.LOCATION,
97-
required: true,
98-
}),
99-
],
100-
},
92+
render: (args) => ({
93+
components: { FormSimple, ActionButton },
94+
setup() {
95+
const { getResponse } = useForm();
96+
const inputs = ref<tFormInput[]>([
97+
new FormInput({
98+
values: [["CO", "", ""]],
99+
name: "location",
100+
type: eFormType.LOCATION,
101+
required: true,
102+
}),
103+
]);
104+
const invalid = ref<iInvalidInput[]>([]);
105+
106+
interface iLocation {
107+
locationCountry: string;
108+
locationState: string;
109+
locationCity: string;
110+
}
111+
112+
async function checkLocation(event: Event) {
113+
const { response, invalidInputs, withErrors, validationHadErrors, errors } =
114+
await getResponse<iLocation, iLocation>(
115+
async (data) => ({ data }),
116+
inputs.value,
117+
event
118+
);
119+
120+
invalid.value = invalidInputs;
121+
122+
if (!withErrors) {
123+
// Succesful request
124+
alert("Success");
125+
console.log(response);
126+
} else if (!validationHadErrors) {
127+
if (!response && !errors) {
128+
alert("Sin cambios");
129+
} else {
130+
alert("Error");
131+
}
132+
}
133+
}
134+
135+
return { args, inputs, invalid, checkLocation };
136+
},
137+
template: `
138+
<div class="flx --flxColumn --flx-start-stretch --gap-30">
139+
<FormSimple v-bind="args" v-model="inputs" v-model:invalid="invalid" />
140+
<ActionButton @click="checkLocation">Check location</ActionButton>
141+
</div>
142+
`,
143+
}),
101144
};
102145

103146
export const WithPhoneField: Story = {

0 commit comments

Comments
 (0)