projects/congarevenuecloud/elements/src/lib/product-card/product-card.component.ts
The Product Card component generates a card template which displays the product information. A product description is displayed if type input is set to 'media'.
import { ProductCardModule } from '@congarevenuecloud/elements';
@NgModule({
imports: [ProductCardModule, ...]
})
export class AppModule {}
// Basic Usage
```typescript
<apt-product-card [product]="product"></apt-product-card>
// All inputs and outputs
```typescript
<apt-product-card
[product]="product"
[thumbnail]="showThumbnail"
[type]="card"
[showCategory]="showingCategory"
[showCode]="showingCode"
[showPrice]="showingPrice"
[canAddToCart]="canAddToCart"
></apt-product-card>
OnInit
OnChanges
OnDestroy
encapsulation | ViewEncapsulation.None |
selector | apt-product-card |
styleUrls | ./product-card.component.scss |
templateUrl | ./product-card.component.html |
Properties |
Inputs |
constructor(config: ConfigurationService, batchSelectionService: BatchSelectionService, productService: ProductService, activatedRoute: ActivatedRoute, router: Router, userService: UserService, storefrontService: StorefrontService, batchActionService: BatchActionService)
|
|||||||||||||||||||||||||||
Parameters :
|
canAddToCart |
Type : boolean
|
Default value : true
|
Flag to show the add to cart button on the card. |
product |
Type : Product | string
|
The product associated with this component. |
quantity |
Type : number
|
The product quantity associated with this component. |
showCategory |
Type : boolean
|
Default value : true
|
Flag to show the category of the product. |
showCode |
Type : boolean
|
Default value : true
|
Flag to show the code of the product. |
showPrice |
Type : boolean
|
Default value : true
|
Flag to show the price of the product. |
showQty |
Type : boolean
|
Default value : false
|
Show quantity. |
skipRules |
Type : boolean
|
Default value : false
|
Rules to be skipped or not. |
thumbnail |
Type : boolean
|
Default value : true
|
Flag to show the thumbnail image on the product card. |
type |
Type : "card" | "media" | "readonly"
|
Default value : 'card'
|
Display type of the product card. |
enableOneTime$ |
Type : Observable<boolean>
|
<ng-container *ngIf="_product && _product[identifier]">
<div class="card" *ngIf="type == 'card'">
<div class="card-body">
<div class="custom-control custom-checkbox custom-checkbox-lg card-title">
<input [id]="_product.Id" type="checkbox" class="custom-control-input" (change)="handleCheckbox($event)"
[checked]="selected$ | async" />
<label class="custom-control-label d-flex justify-content-between d-block d-sm-none text-size-lg" [for]="_product.Id"></label>
<label class="custom-control-label d-flex justify-content-between d-none d-sm-block text-size-xl" [for]="_product.Id"></label>
<div class="d-flex justify-content-between">
<p class="m-0 font-weight-bold d-flex text-break" tooltip="{{_product?.Name}}" container="body"
placement="top">{{ _product?.Name | truncate:30 }}</p>
<span class="pt-1 text-muted icons d-flex">
<i class="fa fa-shopping-bag" tooltip="{{'PRODUCT_CARD.INSTALLED_PRODUCT' | translate}}" container="body"
[adaptivePosition]="false"
*ngIf="aboEnabled && _product?.AssetLineItems?.length > 0 && isLoggedIn$ | async">
</i>
<i class="fa fa-wrench wrench-icon" tooltip="{{'PRODUCT_CARD.COMPLEX_PRODUCT' | translate}}" container="body"
[adaptivePosition]="false" *ngIf="_product.HasAttributes || _product.HasOptions"></i>
</span>
</div>
</div>
<a href="javascript:void(0)" [routerLink]="['/products', _product[identifier]]" [state]="_product">
<div class="img-container">
<img class="card-img-top w-100 h-100 m-auto d-flex align-self-center" [src]="_product.IconId | image"
[alt]="_product.Name" *ngIf="thumbnail">
</div>
<div class="d-flex my-1 align-items-center split-items">
<span class="text-muted product-code pr-1 text-truncate" *ngIf="showCode">{{_product.ProductCode}}</span>
<span class="text-muted product-category pl-1 pr-1 border-left text-truncate"
*ngIf="showCategory && _product.Categories?.length > 0">{{_product.Categories[0]?.Classification?.Name}}</span>
</div>
</a>
<div class="d-flex flex-row">
<apt-popover [placement]="'right'" [popoverContent]="popoverTemplate">
<span class="card-text font-weight-bold d-flex flex-column justify-content-between" *ngIf="showPrice">
<label>{{'PRODUCT_CARD.STANDARD_PRICE' | translate}}
<!-- TODO: Add info icon when DC-8455 implementation is taken up.
<i class="fas fa-info-circle"></i> -->
</label>
<apt-price [record]="_product" [type]="'list'"></apt-price>
</span>
</apt-popover>
</div>
</div>
<div class="card-footer px-2 pb-3 border-top" *ngIf="canAddToCart">
<apt-add-to-cart size="sm" [product]="_product" [label]="label" [assetRoute]="'/assets'"
(updateProductQuantity)="fetchQuantity($event)" [enableOneTime]="enableOneTime$ | async"></apt-add-to-cart>
</div>
</div>
<div *ngIf="type == 'media'" class="media">
<div class="custom-control custom-checkbox custom-checkbox-lg">
<input [id]="_product.Id" type="checkbox" class="custom-control-input" (change)="handleCheckbox($event)"
[checked]="selected$ | async" />
<label class="custom-control-label mt-2 ml-2" [for]="_product.Id"> </label>
</div>
<a href="javascript:void(0)" [routerLink]="['/products', _product[identifier]]"
class="d-flex justify-content-center w-25" [state]="_product">
<img class="mr-3" [src]="_product.IconId | image" [alt]="_product.Name">
</a>
<div class="media-body px-3">
<h5 class="m-0">
<a href="javascript:void(0)" [routerLink]="['/products', _product[identifier]]" [state]="_product">
{{_product.Name}}
</a>
<span class="ml-auto mr-3 purchased list-purchasedbucket">
<i *ngIf="aboEnabled && _product?.AssetLineItems?.length>0 && isLoggedIn$ | async" class="fa fa-shopping-bag"
tooltip="{{'PRODUCT_CARD.INSTALLED_PRODUCT' | translate}}" container="body" [adaptivePosition]="false"
aria-hidden="true"></i>
<i class="fa fa-wrench" tooltip="{{'PRODUCT_CARD.COMPLEX_PRODUCT' | translate}}" container="body"
[adaptivePosition]="false" *ngIf="_product.HasAttributes || _product.HasOptions"></i>
</span>
</h5>
<div class="d-flex mb-3 align-items-center split-items">
<div class="text-muted" *ngIf="showCode">{{_product.ProductCode}}</div>
<div class="text-muted" *ngIf="showCategory && _product.Categories?.length > 0">
{{_product.Categories[0]?.Classification?.Name}}</div>
</div>
<div class="productDescription">
{{_product.Description}}
</div>
</div>
<div class="pl-4 align-self-stretch d-flex align-items-start flex-column">
<strong class="mb-auto align-self-end" *ngIf="showPrice">
<apt-price [record]="_product" [type]="'list'"></apt-price>
</strong>
<div *ngIf="canAddToCart">
<apt-add-to-cart size="sm" [product]="_product" [label]="label" [assetRoute]="'/assets'"
(updateProductQuantity)="fetchQuantity($event)" [enableOneTime]="enableOneTime$ | async">
</apt-add-to-cart>
</div>
</div>
</div>
<div class="card" *ngIf="type === 'readonly'">
<div class="card-body readonly p-2">
<div class="card-title d-flex justify-content-between align-items-start m-0">
<p class="m-0 card-title font-weight-bold text-break" tooltip="{{_product?.Name}}" container="body"
placement="top">{{_product?.Name | truncate:30}}</p>
<button type="button" class="btn btn-link p-0 close" aria-label="Close" (click)="removeProduct()"
*ngIf="selected$ | async">
<span aria-hidden="true">×</span>
</button>
</div>
<a href="javascript:void(0)" [routerLink]="['/products', _product[identifier]]" [state]="_product">
<div class="img-container">
<img class="card-img-top w-100 h-100 m-auto d-flex align-self-center" [src]="_product.IconId | image"
[alt]="_product.Name" *ngIf="thumbnail">
</div>
</a>
<div class="d-flex mt-3 align-items-center split-items" *ngIf="showCategory || showCode">
<span class="text-muted product-code" *ngIf="showCode">{{_product.ProductCode}}</span>
<span class="text-muted product-category"
*ngIf="showCategory && _product.Categories?.length > 0">{{_product.Categories[0].Classification.Name}}</span>
</div>
<div class="d-flex mt-2 justify-content-center" *ngIf="showQty">
<input type="number" [Id]="_product.Id" min="1" class="form-control form-control-sm mb-2 w-50"
(change)="changeQty(_product.Id, _quantity)" [(ngModel)]="_quantity" />
</div>
<span class="card-text font-weight-bold d-flex flex-column justify-content-between" *ngIf="showPrice">
<label>{{'PRODUCT_CARD.STANDARD_PRICE' | translate}}</label>
<apt-price [record]="_product" [type]="'list'"></apt-price>
</span>
</div>
</div>
</ng-container>
<!-- TODO: Add template when DC-8455 implementation is taken up
<ng-template #popoverTemplate>
</ng-template> -->
./product-card.component.scss
apt-product-card {
:host{
display: block;
width: 100% // Added to fix IE 11 issue
}
.card .card-body{
.card-title {
p {
height: 3rem;
}
}
.img-container{
height: 8rem;
}
.card-text{
> span{
font-size: x-small;
}
apt-price {
font-size: large;
}
}
&.readonly{
img{
max-height: 6rem;
max-width: 75%;
}
.img-container{
height: 6rem;
}
}
}
.split-items {
height: 2rem;
>* {
border-radius: 0;
line-height: 15px;
}
}
.product-code{
max-width: 50%;
}
.product-category{
max-width: 50%;
}
.purchased {
float: right;
padding-top: 6px;
}
button.btn.close{
margin-top: -5px;
line-height: 0.9;
}
.btn.btn-primary.dropdown-toggle.dropdown-toggle-split{
height: 31px;
padding-top: 3px;
}
.icons{
white-space: nowrap;
i{
margin-left: 5px;
}
}
.list-purchasedbucket{
font-size: 1rem;
font-weight: 400;
position: absolute;
padding-top: 3px;
.fa{
padding-left: 5px;
}
}
label{
&::before, &::after{
top: 0.15rem;
}
}
.media {
img {
max-height: 8rem;
max-width: 100%;
}
apt-add-to-cart {
form.d-flex {
div:first-child {
justify-content: flex-end !important;
}
}
}
}
.productDescription {
max-height: 100px;
overflow: auto;
}
}