Skip to content

Commit

Permalink
feat: add promocode to checkout page
Browse files Browse the repository at this point in the history
  • Loading branch information
jsapro committed Jan 16, 2024
1 parent 02a5dbc commit 3c29a51
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 5 deletions.
14 changes: 14 additions & 0 deletions src/pages/checkout/checkout.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,20 @@
}
}

.summary__promoError {
min-height: 20px;
text-align: center;
color: $error-color;
font-size: 13px;
font-weight: 300;
line-height: 140%;

@media screen and (width <= 768px) {
font-size: 12px;
min-height: 17px;
}
}

.summary__sale {
max-height: 56px;
display: flex;
Expand Down
84 changes: 79 additions & 5 deletions src/pages/checkout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,23 @@ enum paymentMethodEnum {
online = 'Online',
}

type Promo = {
code: string;
conditions: string;
discount: number;
discount_amount: number;
end_time: null;
id: number;
image: null;
is_active: boolean;
is_constant: boolean;
name: string;
new_total_price: number;
promotion_type: string;
slug: string;
start_time: string;
};

const Checkout: React.FC = () => {
const { isLoggedIn, user } = useAuth();
const { loadCartData, cartData } = useCart();
Expand All @@ -46,6 +63,25 @@ const Checkout: React.FC = () => {
const [comment, setComment] = React.useState<string>('');
const [popupText, setPopupText] = useState('');
const [isAgreed, setIsAgreed] = useState(false);
const [promocodeError, setPromocodeError] = useState('');
const [inputPromoValue, setInputPromoValue] = useState('');
const discountInitial = {
code: '',
conditions: '',
discount: 0,
discount_amount: 0,
end_time: null,
id: 0,
image: null,
is_active: false,
is_constant: false,
name: '',
new_total_price: 0,
promotion_type: '',
slug: '',
start_time: '',
};
const [discount, setDiscount] = useState<Promo>(discountInitial);

const openInfoPopup = (text: string) => {
setPopupText(text);
Expand Down Expand Up @@ -141,6 +177,25 @@ const Checkout: React.FC = () => {
}
});
};

const handleDiscount = (e: React.MouseEvent<HTMLButtonElement>) => {
api
.usersShoppingCartCouponApply({ code: inputPromoValue })
.then((data) => {
setDiscount(data);
setPromocodeError('');
})
.catch((error) => {
setDiscount(discountInitial);
setPromocodeError(error.errors[0].detail);
});
e.preventDefault();
};

const handleInputPromoChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputPromoValue(e.target.value);
};

const handlePaymentChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSelectedPayment(event.target.value);
};
Expand Down Expand Up @@ -446,9 +501,11 @@ const Checkout: React.FC = () => {
<div className={styles.pricelist}>
<div className={styles.pricelist__item}>
<p className={`text_type_u ${styles.summary__title}`}>Товары</p>
<p
className={`text_type_u ${styles.pricelist__price}`}
>{`${cartData.total_price} руб.`}</p>
<p className={`text_type_u ${styles.pricelist__price}`}>{`${
discount && discount.discount !== 0
? discount.new_total_price
: cartData.total_price
} руб.`}</p>
</div>
<div className={styles.pricelist__item}>
<p className={`text_type_u ${styles.summary__title}`}>Упаковка</p>
Expand All @@ -460,15 +517,32 @@ const Checkout: React.FC = () => {
</p>
<p className={`text_type_u ${styles.pricelist__price}`}>0 руб.</p>
</div>
<div className={styles.pricelist__item}>
<p className={`text_type_u ${styles.summary__title}`}>Скидка</p>
<p className={`text_type_u ${styles.pricelist__price}`}>
{discount ? discount.discount_amount : 0} руб.
</p>
</div>
<hr className={styles.pricelist__divider} />
</div>
</div>
<div className={styles.summary__promo}>
<p className={`text_type_u`}>Промокод</p>
<form className={styles.summary__sale} noValidate>
<input type="text" className={`${styles.summary__input_type_sale}`}></input>
<button className={`${styles.summary__btn_type_submit}`}>Применить</button>
<input
value={inputPromoValue}
onChange={handleInputPromoChange}
type="text"
className={`${styles.summary__input_type_sale}`}
></input>
<button
className={`${styles.summary__btn_type_submit}`}
onClick={(e) => handleDiscount(e)}
>
Применить
</button>
</form>
<span className={styles.summary__promoError}>{promocodeError}</span>
</div>
<div className={styles.orderse}>
<button
Expand Down
12 changes: 12 additions & 0 deletions src/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type {
ReviewCreate,
ReviewUpdate,
Payment,
Coupon,
} from './generated-api/data-contracts';
import { BACKEND_URL } from '@data/constants.ts';
import Cookies from 'js-cookie';
Expand Down Expand Up @@ -330,6 +331,17 @@ class Api {
});
}

usersShoppingCartCouponApply(data: Coupon) {
return this._request(`shopping_cart/coupon_apply/`, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
}

/* ----------------------------- Products ----------------------------- */
productsList(slug: string) {
const headers: HeadersInit = {
Expand Down
4 changes: 4 additions & 0 deletions src/services/generated-api/data-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1133,3 +1133,7 @@ export interface OrderCheck {
export type Payment = {
stripe_session_id: string;
};

export interface Coupon {
code: string;
}

0 comments on commit 3c29a51

Please sign in to comment.