mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-20 14:54:15 +01:00
Style cart
This commit is contained in:
parent
5791e6076d
commit
78683a31b3
@ -25,16 +25,13 @@ const CartButton: React.FC = () => {
|
||||
window.location.href = '/#!/cart';
|
||||
};
|
||||
|
||||
if (cart) {
|
||||
return (
|
||||
<div className="cart-button" onClick={showCart}>
|
||||
<i className="fas fa-cart-arrow-down" />
|
||||
<span>{cart.order_items_attributes.length}</span>
|
||||
<div>{t('app.public.cart_button.my_cart')}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
return (
|
||||
<div className="cart-button" onClick={showCart}>
|
||||
<i className="fas fa-cart-arrow-down" />
|
||||
<span>{cart?.order_items_attributes?.length}</span>
|
||||
<p>{t('app.public.cart_button.my_cart')}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const CartButtonWrapper: React.FC = () => {
|
||||
|
@ -15,10 +15,12 @@ import { MemberSelect } from '../user/member-select';
|
||||
import { CouponInput } from '../coupon/coupon-input';
|
||||
import { Coupon } from '../../models/coupon';
|
||||
import { computePriceWithCoupon } from '../../lib/coupon';
|
||||
import noImage from '../../../../images/no_image.png';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
interface StoreCartProps {
|
||||
onSuccess: (message: string) => void,
|
||||
onError: (message: string) => void,
|
||||
userLogin: () => void,
|
||||
currentUser?: User
|
||||
@ -27,10 +29,11 @@ interface StoreCartProps {
|
||||
/**
|
||||
* This component shows user's cart
|
||||
*/
|
||||
const StoreCart: React.FC<StoreCartProps> = ({ onError, currentUser, userLogin }) => {
|
||||
const StoreCart: React.FC<StoreCartProps> = ({ onSuccess, onError, currentUser, userLogin }) => {
|
||||
const { t } = useTranslation('public');
|
||||
|
||||
const { cart, setCart } = useCart(currentUser);
|
||||
console.log('cart: ', cart);
|
||||
const [paymentModal, setPaymentModal] = useState<boolean>(false);
|
||||
|
||||
/**
|
||||
@ -76,14 +79,15 @@ const StoreCart: React.FC<StoreCartProps> = ({ onError, currentUser, userLogin }
|
||||
};
|
||||
|
||||
/**
|
||||
* Open/closes the payment modal
|
||||
* Handle payment
|
||||
*/
|
||||
const handlePaymentSuccess = (data: Order): void => {
|
||||
if (data.payment_state === 'paid') {
|
||||
setPaymentModal(false);
|
||||
window.location.href = '/#!/store';
|
||||
onSuccess(t('app.public.store_cart.checkout_success'));
|
||||
} else {
|
||||
onError('Erreur inconnue after payment, please conntact admin');
|
||||
onError(t('app.public.store_cart.checkout_error'));
|
||||
}
|
||||
};
|
||||
|
||||
@ -117,35 +121,90 @@ const StoreCart: React.FC<StoreCartProps> = ({ onError, currentUser, userLogin }
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the offered item total
|
||||
*/
|
||||
const offeredAmount = (): number => {
|
||||
return cart.order_items_attributes
|
||||
.filter(i => i.is_offered)
|
||||
.map(i => i.amount)
|
||||
.reduce((acc, curr) => acc + curr, 0);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="store-cart">
|
||||
{cart && cartIsEmpty() && <p>{t('app.public.store_cart.cart_is_empty')}</p>}
|
||||
{cart && cart.order_items_attributes.map(item => (
|
||||
<div key={item.id}>
|
||||
<div>{item.orderable_name}</div>
|
||||
<div>{FormatLib.price(item.amount)}</div>
|
||||
<div>{item.quantity}</div>
|
||||
<select value={item.quantity} onChange={changeProductQuantity(item)}>
|
||||
{Array.from({ length: 100 }, (_, i) => i + 1).map(v => (
|
||||
<option key={v} value={v}>{v}</option>
|
||||
))}
|
||||
</select>
|
||||
<div>{FormatLib.price(item.quantity * item.amount)}</div>
|
||||
<FabButton className="delete-btn" onClick={removeProductFromCart(item)}>
|
||||
<i className="fa fa-trash" />
|
||||
</FabButton>
|
||||
<div className='store-cart'>
|
||||
<div className="store-cart-list">
|
||||
{cart && cartIsEmpty() && <p>{t('app.public.store_cart.cart_is_empty')}</p>}
|
||||
{cart && cart.order_items_attributes.map(item => (
|
||||
<article key={item.id} className='store-cart-list-item'>
|
||||
<div className='picture'>
|
||||
<img alt=''src={noImage} />
|
||||
</div>
|
||||
<div className="ref">
|
||||
<span>ref: </span>
|
||||
<p>{item.orderable_name}</p>
|
||||
</div>
|
||||
<div className="actions">
|
||||
<div className='price'>
|
||||
<p>{FormatLib.price(item.amount)}</p>
|
||||
<span>/ {t('app.public.store_cart.unit')}</span>
|
||||
</div>
|
||||
<select value={item.quantity} onChange={changeProductQuantity(item)}>
|
||||
{Array.from({ length: 100 }, (_, i) => i + 1).map(v => (
|
||||
<option key={v} value={v}>{v}</option>
|
||||
))}
|
||||
</select>
|
||||
<div className='total'>
|
||||
<span>{t('app.public.store_cart.total')}</span>
|
||||
<p>{FormatLib.price(item.quantity * item.amount)}</p>
|
||||
</div>
|
||||
<FabButton className="main-action-btn" onClick={removeProductFromCart(item)}>
|
||||
<i className="fa fa-trash" />
|
||||
</FabButton>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="group">
|
||||
<div className='store-cart-info'>
|
||||
<h3>{t('app.public.store_cart.pickup')}</h3>
|
||||
<p>[TODO: texte venant des paramètres de la boutique…]</p>
|
||||
</div>
|
||||
))}
|
||||
{cart && !cartIsEmpty() && cart.user && <CouponInput user={cart.user as User} amount={cart.total} onChange={applyCoupon} />}
|
||||
{cart && !cartIsEmpty() && <p>Total produits: {FormatLib.price(cart.total)}</p>}
|
||||
{cart && !cartIsEmpty() && cart.coupon && computePriceWithCoupon(cart.total, cart.coupon) !== cart.total && <p>Coupon réduction: {FormatLib.price(-(cart.total - computePriceWithCoupon(cart.total, cart.coupon)))}</p>}
|
||||
{cart && !cartIsEmpty() && <p>Total panier: {FormatLib.price(computePriceWithCoupon(cart.total, cart.coupon))}</p>}
|
||||
{cart && !cartIsEmpty() && isPrivileged() && <MemberSelect onSelected={handleChangeMember} />}
|
||||
{cart && !cartIsEmpty() &&
|
||||
<FabButton className="checkout-btn" onClick={checkout}>
|
||||
{t('app.public.store_cart.checkout')}
|
||||
</FabButton>
|
||||
}
|
||||
|
||||
{cart && !cartIsEmpty() && cart.user &&
|
||||
<div className='store-cart-coupon'>
|
||||
<CouponInput user={cart.user as User} amount={cart.total} onChange={applyCoupon} />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<aside>
|
||||
{cart && !cartIsEmpty() && isPrivileged() &&
|
||||
<div> <MemberSelect onSelected={handleChangeMember} /></div>
|
||||
}
|
||||
|
||||
{cart && !cartIsEmpty() && <>
|
||||
<div className="checkout">
|
||||
<h3>{t('app.public.store_cart.checkout_header')}</h3>
|
||||
<span>{t('app.public.store_cart.checkout_products_COUNT', { COUNT: cart?.order_items_attributes.length })}</span>
|
||||
<div className="list">
|
||||
<p>{t('app.public.store_cart.checkout_products_total')} <span>{FormatLib.price(cart.total)}</span></p>
|
||||
{offeredAmount() > 0 &&
|
||||
<p className='gift'>{t('app.public.store_cart.checkout_gift_total')} <span>-{FormatLib.price(offeredAmount())}</span></p>
|
||||
}
|
||||
{cart.coupon && computePriceWithCoupon(cart.total, cart.coupon) !== cart.total &&
|
||||
<p>{t('app.public.store_cart.checkout_coupon')} <span>{FormatLib.price(-(cart.total - computePriceWithCoupon(cart.total, cart.coupon)))}</span></p>
|
||||
}
|
||||
</div>
|
||||
<p className='total'>{t('app.public.store_cart.checkout_total')} <span>{FormatLib.price(computePriceWithCoupon(cart.total, cart.coupon))}</span></p>
|
||||
</div>
|
||||
<FabButton className='checkout-btn' onClick={checkout} disabled={!cart.user || cart.order_items_attributes.length === 0}>
|
||||
{t('app.public.store_cart.checkout')}
|
||||
</FabButton>
|
||||
</>}
|
||||
</aside>
|
||||
|
||||
{cart && !cartIsEmpty() && cart.user && <div>
|
||||
<PaymentModal isOpen={paymentModal}
|
||||
toggleModal={togglePaymentModal}
|
||||
@ -169,4 +228,4 @@ const StoreCartWrapper: React.FC<StoreCartProps> = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
Application.Components.component('storeCart', react2angular(StoreCartWrapper, ['onError', 'currentUser', 'userLogin']));
|
||||
Application.Components.component('storeCart', react2angular(StoreCartWrapper, ['onSuccess', 'onError', 'currentUser', 'userLogin']));
|
||||
|
@ -51,7 +51,18 @@ export const ProductForm: React.FC<ProductFormProps> = ({ product, title, onSucc
|
||||
|
||||
useEffect(() => {
|
||||
ProductCategoryAPI.index().then(data => {
|
||||
setProductCategories(buildSelectOptions(data));
|
||||
// Map product categories by position
|
||||
const sortedCategories = data
|
||||
.filter(c => !c.parent_id)
|
||||
.sort((a, b) => a.position - b.position);
|
||||
const childrenCategories = data
|
||||
.filter(c => typeof c.parent_id === 'number')
|
||||
.sort((a, b) => b.position - a.position);
|
||||
childrenCategories.forEach(c => {
|
||||
const parentIndex = sortedCategories.findIndex(i => i.id === c.parent_id);
|
||||
sortedCategories.splice(parentIndex + 1, 0, c);
|
||||
});
|
||||
setProductCategories(buildSelectOptions(sortedCategories));
|
||||
}).catch(onError);
|
||||
MachineAPI.index({ disabled: false }).then(data => {
|
||||
setMachines(buildChecklistOptions(data));
|
||||
|
@ -1,5 +1,3 @@
|
||||
// TODO: Remove next eslint-disable
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useImmer } from 'use-immer';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@ -35,6 +33,7 @@ interface ProductsProps {
|
||||
const Products: React.FC<ProductsProps> = ({ onSuccess, onError }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [products, setProducts] = useState<Array<Product>>([]);
|
||||
const [filteredProductsList, setFilteredProductList] = useImmer<Array<Product>>([]);
|
||||
const [features, setFeatures] = useImmer<Filters>(initFilters);
|
||||
|
@ -103,6 +103,13 @@ export const StoreProduct: React.FC<StoreProductProps> = ({ productSlug, onError
|
||||
setToCartCount(Number(evt.target.value));
|
||||
};
|
||||
|
||||
/**
|
||||
* Add product to cart
|
||||
*/
|
||||
const addToCart = () => {
|
||||
console.log('Add', toCartCount, 'to cart');
|
||||
};
|
||||
|
||||
if (product) {
|
||||
return (
|
||||
<div className={`store-product ${statusColor(product)}`}>
|
||||
@ -110,14 +117,14 @@ export const StoreProduct: React.FC<StoreProductProps> = ({ productSlug, onError
|
||||
<h2 className='name'>{product.name}</h2>
|
||||
<div className='gallery'>
|
||||
<div className='main'>
|
||||
<div className='aspect-ratio'>
|
||||
<div className='picture'>
|
||||
<img src={productImageUrl(showImage)} alt='' />
|
||||
</div>
|
||||
</div>
|
||||
{product.product_images_attributes.length > 1 &&
|
||||
<div className='thumbnails'>
|
||||
{product.product_images_attributes.map(i => (
|
||||
<div key={i.id} className={`aspect-ratio ${i.id === showImage ? 'is-active' : ''}`}>
|
||||
<div key={i.id} className={`picture ${i.id === showImage ? 'is-active' : ''}`}>
|
||||
<img alt='' onClick={() => setShowImage(i.id)} src={i.attachment_url} />
|
||||
</div>
|
||||
))}
|
||||
@ -167,7 +174,7 @@ export const StoreProduct: React.FC<StoreProductProps> = ({ productSlug, onError
|
||||
value={toCartCount}
|
||||
onChange={evt => typeCount(evt)} />
|
||||
<FabButton onClick={() => setCount('add')} icon={<Plus size={16} />} className="plus" />
|
||||
<FabButton onClick={() => console.log('Add', toCartCount, 'to cart')} icon={<i className="fas fa-cart-arrow-down" />}
|
||||
<FabButton onClick={() => addToCart()} icon={<i className="fas fa-cart-arrow-down" />}
|
||||
className="main-action-btn">
|
||||
{t('app.public.store_product_item.add_to_cart')}
|
||||
</FabButton>
|
||||
|
@ -69,12 +69,6 @@ const Store: React.FC<StoreProps> = ({ onError, currentUser }) => {
|
||||
emitCustomEvent('CartUpdate', cart);
|
||||
}, [cart]);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentUser) {
|
||||
reloadCart();
|
||||
}
|
||||
}, [currentUser]);
|
||||
|
||||
/**
|
||||
* Create categories tree (parent/children)
|
||||
*/
|
||||
|
@ -30,6 +30,8 @@
|
||||
@import "modules/base/fab-text-editor";
|
||||
@import "modules/base/labelled-input";
|
||||
@import "modules/calendar/calendar";
|
||||
@import "modules/cart/cart-button";
|
||||
@import "modules/cart/store-cart";
|
||||
@import "modules/dashboard/reservations/credits-panel";
|
||||
@import "modules/dashboard/reservations/reservations-dashboard";
|
||||
@import "modules/dashboard/reservations/reservations-panel";
|
||||
@ -42,6 +44,7 @@
|
||||
@import "modules/form/form-file-upload";
|
||||
@import "modules/form/form-image-upload";
|
||||
@import "modules/group/change-group";
|
||||
@import "modules/layout/header-page";
|
||||
@import "modules/machines/machine-card";
|
||||
@import "modules/machines/machines-filters";
|
||||
@import "modules/machines/machines-list";
|
||||
|
41
app/frontend/src/stylesheets/modules/cart/cart-button.scss
Normal file
41
app/frontend/src/stylesheets/modules/cart/cart-button.scss
Normal file
@ -0,0 +1,41 @@
|
||||
.cart-button {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0.8rem 0.6rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
background-color: var(--secondary);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
min-width: 2rem;
|
||||
height: 2rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: var(--secondary-text-color);
|
||||
border-radius: 10rem;
|
||||
color: var(--secondary);
|
||||
@include text-sm(600);
|
||||
}
|
||||
i {
|
||||
margin-bottom: 0.8rem;
|
||||
font-size: 2.6rem;
|
||||
columns: var(--secondary-text-color);
|
||||
}
|
||||
p {
|
||||
margin: 0;
|
||||
@include text-sm;
|
||||
text-align: center;
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
}
|
160
app/frontend/src/stylesheets/modules/cart/store-cart.scss
Normal file
160
app/frontend/src/stylesheets/modules/cart/store-cart.scss
Normal file
@ -0,0 +1,160 @@
|
||||
.store-cart {
|
||||
width: 100%;
|
||||
max-width: 1600px;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(12, minmax(0, 1fr));
|
||||
grid-template-rows: minmax(0, min-content);
|
||||
gap: 3.2rem;
|
||||
align-items: flex-start;
|
||||
|
||||
&-list {
|
||||
grid-area: 1 / 1 / 2 / 10;
|
||||
display: grid;
|
||||
gap: 1.6rem;
|
||||
|
||||
&-item {
|
||||
padding: 0.8rem;
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
grid-template-columns: min-content 1fr;
|
||||
gap: 1.6rem;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background-color: var(--gray-soft-lightest);
|
||||
border: 1px solid var(--gray-soft-dark);
|
||||
border-radius: var(--border-radius);
|
||||
|
||||
.picture {
|
||||
width: 10rem !important;
|
||||
@include imageRatio(76%);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
.ref {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
span {
|
||||
@include text-sm;
|
||||
color: var(--gray-hard-lightest);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
p {
|
||||
max-width: 60ch;
|
||||
margin: 0;
|
||||
@include text-base(600);
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
align-self: stretch;
|
||||
padding: 0.8rem;
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 2.4rem;
|
||||
background-color: var(--gray-soft-light);
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
.price,
|
||||
.total {
|
||||
min-width: 10rem;
|
||||
p {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
@include title-base;
|
||||
}
|
||||
span { @include text-sm; }
|
||||
}
|
||||
.total {
|
||||
span {
|
||||
@include text-sm;
|
||||
color: var(--main);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.group {
|
||||
grid-area: 2 / 1 / 3 / 10;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 2.4rem;
|
||||
}
|
||||
&-info,
|
||||
&-coupon {
|
||||
padding: 2.4rem;
|
||||
background-color: var(--gray-soft-light);
|
||||
border-radius: var(--border-radius);
|
||||
h3, label {
|
||||
margin: 0 0 1.6rem;
|
||||
@include text-base(500);
|
||||
color: var(--gray-hard-darkest) !important;
|
||||
}
|
||||
.fab-input .input-wrapper {
|
||||
width: 100%;
|
||||
.fab-input--input {
|
||||
border-radius: var(--border-radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
&-info {
|
||||
p { @include text-sm; }
|
||||
}
|
||||
&-coupon {
|
||||
}
|
||||
|
||||
aside {
|
||||
grid-area: 1 / 10 / 3 / 13;
|
||||
& > div {
|
||||
margin-bottom: 3.2rem;
|
||||
padding: 1.6rem;
|
||||
background-color: var(--gray-soft-lightest);
|
||||
border: 1px solid var(--gray-soft-dark);
|
||||
border-radius: var(--border-radius);
|
||||
h3,
|
||||
.member-select-title {
|
||||
margin: 0 0 2.4rem;
|
||||
padding-bottom: 1.2rem;
|
||||
border-bottom: 1px solid var(--gray-hard);
|
||||
@include title-base;
|
||||
color: var(--gray-hard-dark) !important;
|
||||
}
|
||||
}
|
||||
.checkout {
|
||||
.list {
|
||||
margin: 0.8rem 0 2.4rem;
|
||||
padding: 2.4rem 0;
|
||||
border-top: 1px solid var(--main);
|
||||
border-bottom: 1px solid var(--main);
|
||||
p {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
span { @include title-base; }
|
||||
}
|
||||
.gift { color: var(--information); }
|
||||
}
|
||||
.total {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
@include text-base(600);
|
||||
span { @include title-lg; }
|
||||
}
|
||||
|
||||
&-btn {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding: 1.6rem 0.8rem;
|
||||
background-color: var(--information);
|
||||
border: none;
|
||||
color: var(--gray-soft-lightest);
|
||||
justify-content: center;
|
||||
text-transform: uppercase;
|
||||
&:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
app/frontend/src/stylesheets/modules/layout/header-page.scss
Normal file
37
app/frontend/src/stylesheets/modules/layout/header-page.scss
Normal file
@ -0,0 +1,37 @@
|
||||
.header-page {
|
||||
width: 100%;
|
||||
min-height: 9rem;
|
||||
display: grid;
|
||||
grid-template-columns: min-content 1fr min-content;
|
||||
background-color: var(--gray-soft-lightest);
|
||||
border-bottom: 1px solid var(--gray-soft-dark);
|
||||
|
||||
.back {
|
||||
width: 9rem;
|
||||
border-right: 1px solid var(--gray-soft-dark);
|
||||
a {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: var(--gray-hard-darkest) !important;
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: var(--secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
padding: 3.2rem;
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
min-width: 9rem;
|
||||
border-left: 1px solid var(--gray-soft-dark);
|
||||
}
|
||||
}
|
@ -26,19 +26,8 @@
|
||||
|
||||
.picture {
|
||||
grid-area: image;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding-bottom: 50%;
|
||||
@include imageRatio(50%);
|
||||
border-radius: var(--border-radius);
|
||||
overflow: hidden;
|
||||
img {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
.name {
|
||||
margin: 2.4rem 0 1.6rem;
|
||||
|
@ -57,19 +57,11 @@
|
||||
}
|
||||
.gallery {
|
||||
grid-area: 3 / 1 / 4 / 4;
|
||||
.aspect-ratio {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding-bottom: 100%;
|
||||
overflow: hidden;
|
||||
.picture{
|
||||
@include imageRatio;
|
||||
border-radius: var(--border-radius-sm);
|
||||
border: 1px solid var(--gray-soft-darkest);
|
||||
img {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -184,6 +176,7 @@
|
||||
display: grid;
|
||||
grid-template-areas: "minus input plus"
|
||||
"btn btn btn";
|
||||
grid-template-columns: repeat(3, minmax(0, min-content));
|
||||
gap: 1.6rem;
|
||||
border-top: 1px solid var(--gray-soft-dark);
|
||||
.minus {
|
||||
|
@ -2,4 +2,19 @@
|
||||
--border-radius: 8px;
|
||||
--border-radius-sm: 4px;
|
||||
--shadow: 0 0 10px rgba(39, 32, 32, 0.25);
|
||||
}
|
||||
|
||||
@mixin imageRatio($ratio: 100%) {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding-bottom: $ratio;
|
||||
overflow: hidden;
|
||||
img {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
@ -1,18 +1,12 @@
|
||||
<section class="heading b-b">
|
||||
<div class="row no-gutter">
|
||||
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||
<section class="heading-btn">
|
||||
<a ng-click="backPrevLocation($event)"><i class="fas fa-long-arrow-alt-left "></i></a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l b-r-md">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'app.public.cart.my_cart' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
<div class="header-page">
|
||||
<div class="back">
|
||||
<a ng-click="backPrevLocation($event)"><i class="fas fa-long-arrow-alt-left "></i></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="center">
|
||||
<h1 translate>{{ 'app.public.cart.my_cart' }}</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="m-lg">
|
||||
<store-cart current-user="currentUser" user-login="userLogin" on-error="onError" on-success="onSuccess" />
|
||||
|
@ -1,24 +1,17 @@
|
||||
<section class="heading b-b">
|
||||
<div class="row no-gutter">
|
||||
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||
<section class="heading-btn">
|
||||
<a ng-click="backPrevLocation($event)"><i class="fas fa-long-arrow-alt-left "></i></a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l b-r-md">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'app.public.store.fablab_store' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||
<section class="heading-actions wrapper">
|
||||
</section>
|
||||
</div>
|
||||
<div class="header-page">
|
||||
<div class="back">
|
||||
<a ng-click="backPrevLocation($event)"><i class="fas fa-long-arrow-alt-left "></i></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="center">
|
||||
<h1 translate>{{ 'app.public.store.fablab_store' }}</h1>
|
||||
</div>
|
||||
|
||||
<section>
|
||||
<div class="right">
|
||||
<cart-button />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="m-lg">
|
||||
<store-product product-slug="productSlug" on-error="onError" on-success="onSuccess" />
|
||||
</section>
|
||||
|
@ -1,24 +1,16 @@
|
||||
<section class="heading b-b">
|
||||
<div class="row no-gutter">
|
||||
<div class="col-xs-2 col-sm-2 col-md-1">
|
||||
<section class="heading-btn">
|
||||
<a ng-click="backPrevLocation($event)"><i class="fas fa-long-arrow-alt-left "></i></a>
|
||||
</section>
|
||||
</div>
|
||||
<div class="col-xs-10 col-sm-10 col-md-8 b-l b-r-md">
|
||||
<section class="heading-title">
|
||||
<h1 translate>{{ 'app.public.store.fablab_store' }}</h1>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-12 col-md-3 b-t hide-b-md">
|
||||
<section class="heading-actions wrapper">
|
||||
<cart-button />
|
||||
</section>
|
||||
</div>
|
||||
<div class="header-page">
|
||||
<div class="back">
|
||||
<a ng-click="backPrevLocation($event)"><i class="fas fa-long-arrow-alt-left "></i></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="center">
|
||||
<h1 translate>{{ 'app.public.store.fablab_store' }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<cart-button />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="m-lg">
|
||||
<store current-user="currentUser" on-error="onError" on-success="onSuccess" />
|
||||
|
@ -416,6 +416,17 @@ en:
|
||||
store_cart:
|
||||
checkout: "Checkout"
|
||||
cart_is_empty: "Your cart is empty"
|
||||
pickup: "Pickup your products"
|
||||
unit: "Unit"
|
||||
total: "Total"
|
||||
checkout_header: "Total amount for your cart"
|
||||
checkout_products_COUNT: "Your cart contains {COUNT} {COUNT, plural, =1{product} other{products}}"
|
||||
checkout_products_total: "Product total"
|
||||
checkout_gift_total: "Discount total"
|
||||
checkout_coupon: "Coupon"
|
||||
checkout_total: "Total amount"
|
||||
checkout_error: "An unexpected error occurred. Please contact the administrator."
|
||||
checkout_success: "Purchase confirmed. Thanks!"
|
||||
member_select:
|
||||
select_a_member: "Select a member"
|
||||
start_typing: "Start typing..."
|
||||
|
Loading…
x
Reference in New Issue
Block a user