mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-30 19:52:20 +01:00
Style list items
This commit is contained in:
parent
dc67d08395
commit
d118d045c6
@ -1,7 +1,10 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import FormatLib from '../../lib/format';
|
||||
import { FabButton } from '../base/fab-button';
|
||||
import { Product } from '../../models/product';
|
||||
import { PencilSimple, Trash } from 'phosphor-react';
|
||||
import noImage from '../../../../images/no_image.png';
|
||||
|
||||
interface ProductsListProps {
|
||||
products: Array<Product>,
|
||||
@ -13,6 +16,19 @@ interface ProductsListProps {
|
||||
* This component shows a list of all Products
|
||||
*/
|
||||
export const ProductsList: React.FC<ProductsListProps> = ({ products, onEdit, onDelete }) => {
|
||||
console.log('products: ', products);
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
/**
|
||||
* TODO, document this method
|
||||
*/
|
||||
const thumbnail = (id: number) => {
|
||||
const image = products
|
||||
?.find(p => p.id === id)
|
||||
.product_images_attributes
|
||||
.find(att => att.is_main);
|
||||
return image;
|
||||
};
|
||||
/**
|
||||
* Init the process of editing the given product
|
||||
*/
|
||||
@ -31,15 +47,47 @@ export const ProductsList: React.FC<ProductsListProps> = ({ products, onEdit, on
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns CSS class from stock status
|
||||
*/
|
||||
const statusColor = (product: Product) => {
|
||||
if (product.stock.external === 0 && product.stock.internal === 0) {
|
||||
return 'out-of-stock';
|
||||
}
|
||||
if (product.low_stock_alert) {
|
||||
return 'low';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{products.map((product) => (
|
||||
<div className='products-list-item' key={product.id}>
|
||||
<div className={`products-list-item ${statusColor(product)}`} key={product.id}>
|
||||
<div className='itemInfo'>
|
||||
<img src='https://via.placeholder.com/300' alt='' className='itemInfo-thumbnail' />
|
||||
{/* TODO: image size version ? */}
|
||||
<img src={thumbnail(product.id)?.attachment_url || noImage} alt='' className='itemInfo-thumbnail' />
|
||||
<p className="itemInfo-name">{product.name}</p>
|
||||
</div>
|
||||
<div className=''></div>
|
||||
<div className='details'>
|
||||
<span className={`visibility ${product.is_active ? 'is-active' : ''}`}>
|
||||
{product.is_active
|
||||
? t('app.admin.store.products_list.visible')
|
||||
: t('app.admin.store.products_list.hidden')
|
||||
}
|
||||
</span>
|
||||
<div className='stock'>
|
||||
<span>{t('app.admin.store.products_list.stock.internal')}</span>
|
||||
<p>{product.stock.internal}</p>
|
||||
</div>
|
||||
<div className='stock'>
|
||||
<span>{t('app.admin.store.products_list.stock.external')}</span>
|
||||
<p>{product.stock.external}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>{FormatLib.price(product.amount)}</p>
|
||||
<span>/ {t('app.admin.store.products_list.unit')}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className='actions'>
|
||||
<div className='manage'>
|
||||
<FabButton className='edit-btn' onClick={editProduct(product)}>
|
||||
|
@ -7,6 +7,7 @@ import { FabButton } from '../base/fab-button';
|
||||
import { ProductsList } from './products-list';
|
||||
import { Product } from '../../models/product';
|
||||
import ProductAPI from '../../api/product';
|
||||
import { X } from 'phosphor-react';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -91,11 +92,11 @@ const Products: React.FC<ProductsProps> = ({ onSuccess, onError }) => {
|
||||
<div className='features'>
|
||||
<div className='features-item'>
|
||||
<p>feature name</p>
|
||||
<button><i className="fa fa-times" /></button>
|
||||
<button><X size={16} /></button>
|
||||
</div>
|
||||
<div className='features-item'>
|
||||
<p>long feature name</p>
|
||||
<button><i className="fa fa-times" /></button>
|
||||
<button><X size={16} /></button>
|
||||
</div>
|
||||
</div>
|
||||
<ProductsList
|
||||
|
@ -115,6 +115,8 @@
|
||||
button {
|
||||
width: 3.2rem;
|
||||
height: 3.2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
@ -122,20 +124,25 @@
|
||||
}
|
||||
|
||||
&-item {
|
||||
--status-color: var(--gray-hard-darkest);
|
||||
&.low { --status-color: var(--alert-light); }
|
||||
&.out-of-stock { --status-color: var(--alert); }
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0.6rem 0.8rem;
|
||||
padding: 1.6rem 0.8rem;
|
||||
border: 1px solid var(--gray-soft-dark);
|
||||
border-radius: var(--border-radius);
|
||||
background-color: var(--gray-soft-lightest);
|
||||
&.out-of-stock { border-color: var(--status-color); }
|
||||
&:not(:first-child) {
|
||||
margin-top: 1.6rem;
|
||||
}
|
||||
|
||||
.itemInfo {
|
||||
min-width: 20ch;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
&-thumbnail {
|
||||
@ -153,6 +160,46 @@
|
||||
color: var(--gray-hard-darkest);
|
||||
}
|
||||
}
|
||||
.details {
|
||||
display: grid;
|
||||
grid-template-columns: 140px repeat(3, minmax(120px, 1fr));
|
||||
justify-items: flex-start;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin-left: auto;
|
||||
margin-right: 4rem;
|
||||
p {
|
||||
margin: 0;
|
||||
@include text-base(600);
|
||||
}
|
||||
|
||||
.visibility {
|
||||
justify-self: center;
|
||||
padding: 0.4rem 0.8rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: var(--gray-soft-light);
|
||||
border-radius: var(--border-radius);
|
||||
&::before {
|
||||
flex-shrink: 0;
|
||||
margin-right: 1rem;
|
||||
content: "";
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background-color: var(--gray-hard);
|
||||
border-radius: 50%;
|
||||
}
|
||||
&.is-active::before {
|
||||
background-color: var(--success);
|
||||
}
|
||||
}
|
||||
.stock {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: var(--status-color);
|
||||
span { @include text-xs; }
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
@ -169,7 +216,7 @@
|
||||
&:hover { opacity: 0.75; }
|
||||
}
|
||||
.edit-btn {background: var(--gray-hard-darkest) }
|
||||
.delete-btn {background: var(--error) }
|
||||
.delete-btn {background: var(--main) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,12 @@
|
||||
font-size: 1.4rem;
|
||||
line-height: normal;
|
||||
}
|
||||
@mixin text-xs($weight: normal) {
|
||||
font-family: var(--font-text);
|
||||
font-weight: $weight;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.18;
|
||||
}
|
||||
|
||||
// Text Editor
|
||||
@mixin editor {
|
||||
|
@ -1933,6 +1933,13 @@ en:
|
||||
create_a_product: "Create a product"
|
||||
successfully_deleted: "The product has been successfully deleted"
|
||||
unable_to_delete: "Unable to delete the product: "
|
||||
products_list:
|
||||
visible: "visible"
|
||||
hidden: "hidden"
|
||||
stock:
|
||||
internal: "Private stock"
|
||||
external: "Public stock"
|
||||
unit: "unit"
|
||||
new_product:
|
||||
add_a_new_product: "Add a new product"
|
||||
successfully_created: "The new product has been created."
|
||||
|
Loading…
x
Reference in New Issue
Block a user