Skip to content

Commit

Permalink
refactor(RSS-ECOMM-4_39): search params (#331)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kleostro authored Jun 3, 2024
1 parent 1b45d94 commit 39d0992
Show file tree
Hide file tree
Showing 18 changed files with 241 additions and 114 deletions.
47 changes: 21 additions & 26 deletions src/app/Router/model/RouterModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import showErrorMessage from '@/shared/utils/userMessage.ts';
const DEFAULT_SEGMENT = import.meta.env.VITE_APP_DEFAULT_SEGMENT;
const NEXT_SEGMENT = import.meta.env.VITE_APP_NEXT_SEGMENT;
const PATH_SEGMENTS_TO_KEEP = import.meta.env.VITE_APP_PATH_SEGMENTS_TO_KEEP;
const SEARCH_SEGMENT = import.meta.env.VITE_APP_SEARCH_SEGMENT;

class RouterModel {
private static router: RouterModel;
Expand All @@ -23,17 +24,19 @@ class RouterModel {

this.routes = routes;
document.addEventListener('DOMContentLoaded', () => {
const currentPath = window.location.pathname.slice(NEXT_SEGMENT).split(DEFAULT_SEGMENT) || PAGE_ID.DEFAULT_PAGE;
const currentPath =
(window.location.pathname + window.location.search).slice(NEXT_SEGMENT).split(DEFAULT_SEGMENT) ||
PAGE_ID.DEFAULT_PAGE;
this.navigateTo(currentPath.join(DEFAULT_SEGMENT));
});

window.addEventListener('popstate', (event) => {
const currentState: unknown = event.state;
let currentPage = '';
let [currentPage] = '';
let currentPath = '';

if (isValidState(currentState)) {
currentPage = currentState.path.split(DEFAULT_SEGMENT)[PATH_SEGMENTS_TO_KEEP] + DEFAULT_SEGMENT;
[currentPage] = currentState.path.split(DEFAULT_SEGMENT)[PATH_SEGMENTS_TO_KEEP].split(SEARCH_SEGMENT);
currentPath = currentState.path;
}

Expand All @@ -49,21 +52,21 @@ class RouterModel {
public static appendSearchParams(key: string, value: string): void {
const url = new URL(decodeURIComponent(window.location.href));
url.searchParams.append(key, value);
const path = url.pathname + encodeURIComponent(url.search);
window.history.pushState({ path: path.slice(1) }, '', path);
const path = url.pathname + url.search.toString();
window.history.pushState({ path: path.slice(NEXT_SEGMENT) }, '', path);
}

public static clearSearchParams(): void {
const url = new URL(decodeURIComponent(window.location.href));
const path = `${DEFAULT_SEGMENT}${url.pathname.split(DEFAULT_SEGMENT)[NEXT_SEGMENT]}${DEFAULT_SEGMENT}`;
window.history.pushState({ path: path.slice(1) }, '', path);
window.history.pushState({ path: path.slice(NEXT_SEGMENT) }, '', path);
}

public static deleteSearchParams(key: string): void {
const url = new URL(decodeURIComponent(window.location.href));
url.searchParams.delete(key);
const path = url.pathname + encodeURIComponent(url.search);
window.history.pushState({ path: path.slice(1) }, '', path);
const path = url.pathname + url.search.toString();
window.history.pushState({ path: path.slice(NEXT_SEGMENT) }, '', path);
}

public static getInstance(): RouterModel {
Expand All @@ -78,17 +81,16 @@ class RouterModel {
const url = new URL(decodeURIComponent(window.location.href));
url.searchParams.delete(key);
url.searchParams.set(key, value);
const path = url.pathname + encodeURIComponent(url.search);
window.history.pushState({ path: path.slice(1) }, '', path);
const path = url.pathname + url.search.toString();
window.history.pushState({ path: path.slice(NEXT_SEGMENT) }, '', path);
}

private async checkPageAndParams(
currentPage: string,
path: string,
): Promise<{ hasRoute: boolean; params: PageParams } | null> {
const hasRoute = this.routes.has(currentPage);
const decodePath = decodeURIComponent(path);
const id = decodePath.split(DEFAULT_SEGMENT).slice(PATH_SEGMENTS_TO_KEEP, -NEXT_SEGMENT)[NEXT_SEGMENT];
const id = path.split(DEFAULT_SEGMENT)[NEXT_SEGMENT]?.split(SEARCH_SEGMENT)[PATH_SEGMENTS_TO_KEEP] || null;

setPageTitle(currentPage, hasRoute);
observeStore(selectCurrentLanguage, () => this.checkPageAndParams(currentPage, path));
Expand All @@ -100,11 +102,7 @@ class RouterModel {

return {
hasRoute,
params: {
[currentPage.slice(PATH_SEGMENTS_TO_KEEP, -NEXT_SEGMENT)]: {
id: id ?? null,
},
},
params: { [currentPage.slice(PATH_SEGMENTS_TO_KEEP)]: { id } },
};
}

Expand All @@ -119,15 +117,12 @@ class RouterModel {
}

public navigateTo(path: string): void {
const currentPage = path.split(DEFAULT_SEGMENT)[PATH_SEGMENTS_TO_KEEP] + DEFAULT_SEGMENT || PAGE_ID.DEFAULT_PAGE;
if (currentPage !== getStore().getState().currentPage) {
this.checkPageAndParams(currentPage, path)
.then((check) => {
if (check) {
this.routes.get(currentPage)?.(check.params).catch(showErrorMessage);
}
})
.catch(showErrorMessage);
const currentPage =
path.split(DEFAULT_SEGMENT)[PATH_SEGMENTS_TO_KEEP].split(SEARCH_SEGMENT)[PATH_SEGMENTS_TO_KEEP] ||
PAGE_ID.DEFAULT_PAGE;

if (currentPage !== getStore().getState().currentPage || currentPage === PAGE_ID.DEFAULT_PAGE) {
this.handleRequest(currentPage, path);
}
history.pushState({ path }, '', `/${path}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import ButtonModel from '@/shared/Button/model/ButtonModel.ts';
import LoaderModel from '@/shared/Loader/model/LoaderModel.ts';
import modal from '@/shared/Modal/model/ModalModel.ts';
import { LOADER_SIZE } from '@/shared/constants/sizes.ts';
import SVG_DETAILS from '@/shared/constants/svg.ts';
import createBaseElement from '@/shared/utils/createBaseElement.ts';
import createSVGUse from '@/shared/utils/createSVGUse.ts';

import styles from './productModalSliderView.module.scss';

Expand Down Expand Up @@ -119,13 +121,20 @@ class ProductModalSliderView {
this.nextSlideButton = new ButtonModel({
classes: [styles.nextSlideButton],
});

const svg = document.createElementNS(SVG_DETAILS.SVG_URL, 'svg');
svg.append(createSVGUse(SVG_DETAILS.ARROW_UP));
this.nextSlideButton.getHTML().append(svg);
return this.nextSlideButton;
}

private createPrevSlideButton(): ButtonModel {
this.prevSlideButton = new ButtonModel({
classes: [styles.prevSlideButton],
});
const svg = document.createElementNS(SVG_DETAILS.SVG_URL, 'svg');
svg.append(createSVGUse(SVG_DETAILS.ARROW_UP));
this.prevSlideButton.getHTML().append(svg);
return this.prevSlideButton;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,9 @@

.nextSlideButton,
.prevSlideButton {
position: relative;
display: block;
display: flex;
align-items: center;
justify-content: center;
border: var(--one) solid var(--noble-gray-200);
border-radius: 50%;
width: 3rem;
Expand All @@ -92,10 +93,21 @@
border-color 0.2s,
transform 0.2s;

svg {
width: 2.5rem;
height: 2.5rem;
stroke: var(--steam-green-800);
transition: stroke 0.2s;
}

@media (hover: hover) {
&:hover {
border-color: var(--steam-green-400);
color: var(--steam-green-700);

svg {
stroke: var(--steam-green-1100);
}
}
}

Expand All @@ -106,22 +118,14 @@
}

.nextSlideButton {
&::after {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) rotate(90deg);
svg {
transform: rotate(90deg);
}
}

.prevSlideButton {
&::after {
content: '';
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) rotate(-90deg);
svg {
transform: rotate(-90deg);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/features/CountryChoice/view/countryChoiceView.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@
border: 1px solid var(--noble-gray-300);
border-radius: var(--small-br);
width: 100%;
min-height: calc(var(--extra-large-offset) * 2); // 200px
max-height: calc(var(--extra-large-offset) * 2); // 200px
min-height: calc(var(--extra-large-offset) * 1.3);
max-height: calc(var(--extra-large-offset) * 1.3);
background-color: var(--white);
opacity: 1;
visibility: visible;
Expand Down
4 changes: 4 additions & 0 deletions src/features/ProductFilters/view/ProductFiltersView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,10 @@ class ProductFiltersView {
this.callback();
});

observeStore(selectCurrentLanguage, () => {
this.resetFiltersButton.getHTML().textContent = BUTTON_TEXT[getStore().getState().currentLanguage].RESET;
});

return this.resetFiltersButton;
}

Expand Down
44 changes: 22 additions & 22 deletions src/pages/CartPage/model/CartPageModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,6 @@ import ProductOrderModel from '@/widgets/ProductOrder/model/ProductOrderModel.ts
import CartPageView from '../view/CartPageView.ts';

class CartPageModel implements Page {
private addDiscountHandler = async (discountCode: string): Promise<void> => {
if (discountCode.trim()) {
const loader = new LoaderModel(LOADER_SIZE.SMALL).getHTML();
this.view.getCouponButton().append(loader);
await getCartModel()
.addCoupon(discountCode)
.then((cart) => {
if (cart) {
serverMessageModel.showServerMessage(
SERVER_MESSAGE_KEYS.SUCCESSFUL_ADD_COUPON_TO_CART,
MESSAGE_STATUS.SUCCESS,
);
this.cart = cart;
this.view.updateTotal(this.cart);
}
})
.catch(showErrorMessage)
.finally(() => loader.remove());
}
};

private cart: Cart | null = null;

private changeProductHandler = (cart: Cart): void => {
Expand Down Expand Up @@ -83,11 +62,32 @@ class CartPageModel implements Page {
private view: CartPageView;

constructor(parent: HTMLDivElement) {
this.view = new CartPageView(parent, this.clearCart, this.addDiscountHandler);
this.view = new CartPageView(parent, this.clearCart, this.addDiscountHandler.bind(this));

this.init().catch(showErrorMessage);
}

private async addDiscountHandler(discountCode: string): Promise<void> {
if (discountCode.trim()) {
const loader = new LoaderModel(LOADER_SIZE.SMALL).getHTML();
this.view.getCouponButton().append(loader);
await getCartModel()
.addCoupon(discountCode)
.then((cart) => {
if (cart) {
serverMessageModel.showServerMessage(
SERVER_MESSAGE_KEYS.SUCCESSFUL_ADD_COUPON_TO_CART,
MESSAGE_STATUS.SUCCESS,
);
this.cart = cart;
this.view.updateTotal(this.cart);
}
})
.catch(showErrorMessage)
.finally(() => loader.remove());
}
}

private async init(): Promise<void> {
getStore().dispatch(setCurrentPage(PAGE_ID.CART_PAGE));
this.cart = await getCartModel().addProductInfo();
Expand Down
29 changes: 29 additions & 0 deletions src/pages/CartPage/view/cartPageView.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -161,11 +161,40 @@
}

.continue {
position: relative;
align-self: center;
padding: var(--tiny-offset) 0;
font: var(--regular-font);
color: var(--steam-green-800);
transition: color 0.2s;
cursor: pointer;

&::after {
content: '';
position: absolute;
left: 0;
bottom: 0.3rem;
width: 100%;
height: var(--two);
background-color: currentcolor;
opacity: 0;
transform: scaleX(0);
transform-origin: center;
transition:
transform 0.2s,
opacity 0.2s;
}

@media (hover: hover) {
&:hover {
color: var(--steam-green-800);

&::after {
opacity: 1;
transform: scaleX(1);
}
}
}
}

.mobileHide {
Expand Down
4 changes: 2 additions & 2 deletions src/shared/ServerMessage/view/serverMessageView.module.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.serverMessageWrapper {
position: fixed;
right: 0;
top: 50%;
top: 20%;
z-index: 15;
border: var(--two) solid var(--steam-green-800);
border-top: var(--tiny-offset) solid var(--steam-green-800);
Expand All @@ -13,7 +13,7 @@
word-break: break-word;
text-align: center;
background-color: var(--white);
transform: translate(110%, -50%);
transform: translate(110%, -80%);
}

.progressBar {
Expand Down
6 changes: 3 additions & 3 deletions src/shared/Store/test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ vi.mock('./Store.ts', async (importOriginal) => {
authToken: null,
billingCountry: '',
currentLanguage: 'en',
currentPage: '/',
currentPage: '',
defaultCountry: '',
isAppThemeLight: true,
isUserLoggedIn: false,
Expand Down Expand Up @@ -178,7 +178,7 @@ describe('rootReducer', () => {
authToken: null,
billingCountry: '',
currentLanguage: 'en',
currentPage: '/',
currentPage: '',
defaultCountry: '',
isAppThemeLight: true,
isUserLoggedIn: false,
Expand Down Expand Up @@ -215,7 +215,7 @@ describe('rootReducer', () => {
});

it('should handle setCurrentPage action', () => {
const page = 'main/';
const page = 'main';
const action = actions.setCurrentPage(PAGE_ID.MAIN_PAGE);
const newState = rootReducer(initialState, action);
expect(newState.currentPage).toEqual(page);
Expand Down
6 changes: 3 additions & 3 deletions src/shared/constants/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ export const PRICE_RANGE_LABEL = {

export const META_FILTERS = {
en: {
ALL_PRODUCTS: 'All',
NEW_ARRIVALS: 'New',
SALE: 'Sale',
ALL_PRODUCTS: 'all',
NEW_ARRIVALS: 'new',
SALE: 'sale',
},
ru: {
ALL_PRODUCTS: 'Все',
Expand Down
Loading

0 comments on commit 39d0992

Please sign in to comment.