Skip to content

Commit

Permalink
Remove @zenky/ui dependency; use Result interfaces in async operations
Browse files Browse the repository at this point in the history
Update ApiErrorHandler
  • Loading branch information
tzurbaev committed Sep 2, 2022
1 parent 80239f1 commit b71bfdc
Show file tree
Hide file tree
Showing 33 changed files with 479 additions and 531 deletions.
230 changes: 9 additions & 221 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenky/storefront-vue",
"version": "0.9.41",
"version": "0.9.42",
"description": "Zenky Storefront library for Vue 3.",
"author": "Timur Zurbaev <hello@zurbaev.ru>",
"license": "MIT",
Expand All @@ -20,8 +20,7 @@
],
"peerDependencies": {
"@zenky/api": "^0.9.51",
"@zenky/events": "^1.0.2",
"@zenky/ui": "^0.9.63",
"@zenky/events": "^1.0.3",
"date-fns": "^2.29.2",
"lodash-es": "^4.17.21",
"pinia": "^2.0.14",
Expand Down
1 change: 0 additions & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export default [
external: [
'@zenky/api',
'@zenky/events',
'@zenky/ui',
'date-fns',
'lodash-es',
'pinia',
Expand Down
7 changes: 4 additions & 3 deletions src/addresses/dadata/dadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { computed, ComputedRef, Ref, ref, watch } from 'vue';
import { getCityPart, getDaDataEntityName, getHousePart } from './helpers.js';
import { debounce } from 'lodash-es';
import { useStoreStore } from '../../store/index.js';
import { storeToRefs } from 'pinia';

export interface DadataProvider {
query: Ref<string | null>;
Expand All @@ -11,13 +12,13 @@ export interface DadataProvider {
}

export function useDadata(): DadataProvider {
const { cityId } = useStoreStore();
const { cityId } = storeToRefs(useStoreStore());
const query = ref<string | null>(null);
const loading = ref<boolean>(false);
const results = ref<any[]>([]);

watch(query, debounce(async () => {
if (loading.value || !query.value || !cityId) {
if (loading.value || !query.value || !cityId.value) {
return;
}

Expand All @@ -26,7 +27,7 @@ export function useDadata(): DadataProvider {

const { suggestions } = await getAddressSuggestions({
query: query.value,
city_id: cityId,
city_id: cityId.value,
});

results.value = suggestions;
Expand Down
18 changes: 14 additions & 4 deletions src/addresses/form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,21 @@ export interface AddressFormValue {
floor: string;
has_intercom: boolean;
}

export interface AddressFormValueProvider {
errors: string[];
data: AddressFormValue;
}

export enum AddressFormValueError {
DaDataSuggestionRequired = 'dadata.suggestion_required',
CityRequired = 'plain.city_required',
StreetRequired = 'plain.street_required',
HouseRequired = 'plain.house_required',
StockRequired = 'stock_required',
TableRequired = 'table_required',
}

export function useAddressFormValue(
form: AddressForm,
resolver: string,
Expand Down Expand Up @@ -77,15 +87,15 @@ export function useAddressFormValue(
: form.has_intercom === 'true',
} as AddressFormValue;
} else {
errors.push('Нужно выбрать улицу из выпадающего списка.');
errors.push(AddressFormValueError.DaDataSuggestionRequired);
}
} else if (resolver === 'plain') {
if (!form.city) {
errors.push('Нужно указать город.');
errors.push(AddressFormValueError.CityRequired);
} else if (!form.street) {
errors.push('Нужно указать улицу.');
errors.push(AddressFormValueError.StreetRequired);
} else if (!form.house) {
errors.push('Нужно указать номер дома.');
errors.push(AddressFormValueError.HouseRequired);
} else {
data = {
city: form.city,
Expand Down
1 change: 1 addition & 0 deletions src/catalog/collections/composables/collections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export function useCollections(): ProductsCollectionsProvider {
const collections = ref<ProductsCollection[]>([]);
const load = async (ids: string[] | null = null): Promise<void> => {
collections.value = [];

const items = await getCollections();

if (ids === null) {
Expand Down
10 changes: 2 additions & 8 deletions src/catalog/features/composables/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import { ListLoader, useListLoader } from '../../../loaders.js';
import {
Feature,
FeaturesGroupContainer,
getApiErrorMessage,
getCategoryFeatures,
getCategoryFeaturesGroups,
ResourceRequest,
} from '@zenky/api';
import { useNotification } from '@zenky/ui';

export function useCategoryFeaturesList(categoryId: string | null, errorHandler?: OptionalApiErrorHandler): ListLoader<Feature> {
return useListLoader<Feature, ResourceRequest>(
Expand All @@ -20,9 +18,7 @@ export function useCategoryFeaturesList(categoryId: string | null, errorHandler?
return getCategoryFeatures(categoryId);
},

getApiErrorHandler(errorHandler, function (e) {
useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось загрузить список фильтров.'));
}),
getApiErrorHandler(errorHandler, 'useCategoryFeaturesList', 'Unable to load category features list.'),
);
}

Expand All @@ -39,8 +35,6 @@ export function useCategoryFeaturesGroupsList(
return getCategoryFeaturesGroups(categoryId);
},

getApiErrorHandler(errorHandler, function (e) {
useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось загрузить список фильтров.'));
}),
getApiErrorHandler(errorHandler, 'useCategoryFeaturesGroupsList', 'Unable to load category features groups list.'),
);
}
14 changes: 3 additions & 11 deletions src/content/articles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,17 @@ import {
ArticleCategoriesPaginationRequest,
ArticleCategory,
ArticlesPaginationRequest,
getApiErrorMessage,
getArticle,
getArticleCategories,
getArticles,
} from '@zenky/api';
import { useNotification } from '@zenky/ui';

export function useArticlesList(
errorHandler?: OptionalApiErrorHandler,
): PaginatedLoader<Article, ArticlesPaginationRequest> {
return usePaginatedLoader<Article, ArticlesPaginationRequest>(
getArticles,
getApiErrorHandler(errorHandler, function (e) {
useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось загрузить список статей.'));
}),
getApiErrorHandler(errorHandler, 'useArticlesList', 'Unable to load articles list.'),
);
}

Expand All @@ -28,14 +24,10 @@ export function useArticleCategoriesList(
): PaginatedLoader<ArticleCategory, ArticleCategoriesPaginationRequest> {
return usePaginatedLoader<ArticleCategory, ArticleCategoriesPaginationRequest>(
getArticleCategories,
getApiErrorHandler(errorHandler, function (e) {
useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось загрузить список категорий статей.'));
}),
getApiErrorHandler(errorHandler, 'useArticleCategoriesList', 'Unable to load article categories list.'),
);
}

export function useArticleItem(errorHandler?: OptionalApiErrorHandler): ItemLoader<Article> {
return useItemLoader<Article>(getArticle, getApiErrorHandler(errorHandler, function (e) {
useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось загрузить статью.'));
}));
return useItemLoader<Article>(getArticle, getApiErrorHandler(errorHandler, 'useArticleItem', 'Unable to load article.'));
}
48 changes: 28 additions & 20 deletions src/customer/composables/addresses.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { getApiErrorHandler, OptionalApiErrorHandler } from '../../errors.js';
import { PaginatedLoader, usePaginatedLoader } from '../../loaders.js';
import { Address, deleteAddress, getApiErrorMessage, getCustomerAddresses, updateAddress } from '@zenky/api';
import { useNotification } from '@zenky/ui';
import { Address, deleteAddress, getApiError, getCustomerAddresses, updateAddress } from '@zenky/api';
import { DataDestroyer, useDataDestroyer } from '../../destroyers.js';
import { EditAddressFormProvider } from '../types.js';
import { AddressResult, AddressResultReason, AddressResultType, EditAddressFormProvider } from '../types.js';
import { AddressForm, getExistedAddressDisplayValue, useAddressFormValue } from '../../addresses/index.js';
import { ref } from 'vue';

export function useDeliveryAddressesList(errorHandler?: OptionalApiErrorHandler): PaginatedLoader<Address> {
return usePaginatedLoader<Address>(getCustomerAddresses, getApiErrorHandler(errorHandler, function (e) {
useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось загрузить адреса доставки.'));
}));
return usePaginatedLoader<Address>(
getCustomerAddresses,
getApiErrorHandler(errorHandler, 'useDeliveryAddressesList', 'Unable to load delivery addresses list.'),
);
}

export function useDeliveryAddressDestroyer(errorHandler?: OptionalApiErrorHandler): DataDestroyer {
return useDataDestroyer(deleteAddress, getApiErrorHandler(errorHandler, function (e) {
useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось удалить адрес доставки.'));
}));
return useDataDestroyer(
deleteAddress,
getApiErrorHandler(errorHandler, 'useDeliveryAddressDestroyer', 'Unable to delete delivery address.'),
);
}

export function useEditAddressForm(address: Address): EditAddressFormProvider {
Expand Down Expand Up @@ -46,17 +47,22 @@ export function useEditAddressForm(address: Address): EditAddressFormProvider {
const saving = ref<boolean>(false);
const form = ref<AddressForm>(addressFields);

const save = async (): Promise<boolean> => {
const save = async (): Promise<AddressResult> => {
if (saving.value) {
return false;
return {
type: AddressResultType.Failed,
reason: AddressResultReason.InProgress,
};
}

const { errors, data } = useAddressFormValue(form.value, address.resolver, address);

if (errors.length > 0) {
useNotification('error', 'Ошибка', errors[0]);

return false;
return {
type: AddressResultType.Failed,
reason: AddressResultReason.Validation,
data: errors,
};
}

saving.value = true;
Expand All @@ -69,16 +75,18 @@ export function useEditAddressForm(address: Address): EditAddressFormProvider {
},
});

useNotification('success', 'Адрес сохранён', 'Адрес был успешно сохранён!');

return true;
return {
type: AddressResultType.Completed,
};
} catch (e) {
useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось сохранить адрес. Повторите попытку.'));
return {
type: AddressResultType.Failed,
reason: AddressResultReason.ApiError,
error: getApiError(e),
};
} finally {
saving.value = false;
}

return false;
};

return {
Expand Down
28 changes: 14 additions & 14 deletions src/customer/composables/authentication/check.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { ref, Ref } from 'vue';
import {
AuthenticationEvent,
AuthenticationFailureReason,
AuthenticationForm,
AuthenticationResult,
AuthenticationResultType,
AuthenticationStage,
AuthenticationStatusCheckerProvider,
EmitAuthenticationEvent,
} from '../../types.js';
import { useNotification } from '@zenky/ui';
import { getApiErrorMessage, getAuthenticationStatus } from '@zenky/api';
import { getApiError, getAuthenticationStatus } from '@zenky/api';

export function useAuthenticationStatusChecker(
form: Ref<AuthenticationForm>,
Expand All @@ -19,14 +19,13 @@ export function useAuthenticationStatusChecker(
const check = async (): Promise<AuthenticationResult> => {
if (active.value) {
return {
type: AuthenticationResultType.Pending,
type: AuthenticationResultType.Failed,
reason: AuthenticationFailureReason.InProgress,
};
} else if (!form.value.phone.number || !form.value.phone.country) {
useNotification('error', 'Ошибка', 'Нужно указать номер телефона.');

return {
type: AuthenticationResultType.Validation,
data: 'phone',
reason: AuthenticationFailureReason.PhoneRequired,
};
}

Expand All @@ -39,33 +38,34 @@ export function useAuthenticationStatusChecker(
emit(AuthenticationEvent.Stage, AuthenticationStage.Register);

return {
type: AuthenticationResultType.Completed,
type: AuthenticationResultType.Stage,
data: AuthenticationStage.Register,
};
} else if (!status.confirmed) {
emit(AuthenticationEvent.Stage, AuthenticationStage.Confirmation);

return {
type: AuthenticationResultType.Completed,
type: AuthenticationResultType.Stage,
data: AuthenticationStage.Confirmation,
};
}

emit(AuthenticationEvent.Stage, AuthenticationStage.Login);

return {
type: AuthenticationResultType.Completed,
type: AuthenticationResultType.Stage,
data: AuthenticationStage.Login,
};
} catch (e) {
useNotification('error', 'Ошибка', getApiErrorMessage(e, 'Не удалось проверить статус регистрации. Повторите попытку.'));

return {
type: AuthenticationResultType.Failed,
reason: AuthenticationFailureReason.ApiError,
error: getApiError(e),
};
} finally {
active.value = false;
}

return {
type: AuthenticationResultType.Failed,
};
};

return {
Expand Down
Loading

0 comments on commit b71bfdc

Please sign in to comment.