home page

This commit is contained in:
Betteloni 2024-10-23 18:48:28 -03:00
parent dd1b2763d8
commit 5608fa4184
18 changed files with 546 additions and 103 deletions

View file

@ -37,7 +37,8 @@
"node_modules/nebular-icons/scss/nebular-icons.scss",
"node_modules/pace-js/templates/pace-theme-flash.tmpl.css",
"node_modules/leaflet/dist/leaflet.css",
"src/app/@theme/styles/styles.scss"
"src/app/@theme/styles/styles.scss",
"node_modules/mdb-angular-ui-kit/assets/scss/mdb.scss"
],
"scripts": [
"node_modules/pace-js/pace.min.js",

19
package-lock.json generated
View file

@ -40,6 +40,7 @@
"intl": "1.2.5",
"ionicons": "2.0.1",
"leaflet": "1.2.0",
"mdb-angular-ui-kit": "^4.1.0",
"nebular-icons": "1.1.0",
"ng2-ckeditor": "~1.2.9",
"ng2-completer": "^9.0.1",
@ -1349,6 +1350,7 @@
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-15.2.10.tgz",
"integrity": "sha512-/TSnm/ZQML6A4lvunyN2tjTB5utuvk3d1Pnfyehp/FXtV6YfZm6+EZrOpKkKPCxTuAgW6c9KK4yQtt3RuNVpwQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@angular-devkit/architect": "0.1502.10",
"@angular-devkit/core": "15.2.10",
@ -5949,6 +5951,7 @@
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==",
"dev": true,
"hasInstallScript": true,
"license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)",
"engines": {
"node": ">=6"
}
@ -18654,6 +18657,22 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/mdb-angular-ui-kit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/mdb-angular-ui-kit/-/mdb-angular-ui-kit-4.1.0.tgz",
"integrity": "sha512-9W6JZDsizTq8aVIDucIQpPqdiw0p3ILYf25lH76u/9UfjNf5M1LchMfDc1PiL3FSEpU+OImZ0LbAMLzhGvZn9g==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/animations": "^15.0.0",
"@angular/cdk": "^15.0.0",
"@angular/common": "^15.0.0",
"@angular/core": "^15.0.0",
"@angular/forms": "^15.0.0"
}
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",

View file

@ -60,6 +60,7 @@
"intl": "1.2.5",
"ionicons": "2.0.1",
"leaflet": "1.2.0",
"mdb-angular-ui-kit": "^4.1.0",
"nebular-icons": "1.1.0",
"ng2-ckeditor": "~1.2.9",
"ng2-completer": "^9.0.1",

View file

@ -1,36 +1,14 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { delay, map } from 'rxjs/operators';
import { Apollo } from 'apollo-angular';
import { FIND_UNIQUE_BANNER, LIST_BANNERS } from './graphql/queries';
import { Banner } from './banner.model';
import { CREATE_BANNER, UPDATE_BANNER } from './graphql/mutations';
const TOTAL_PAGES = 7;
export class NewsPost {
title: string;
link: string;
creator: string;
text: string;
}
@Injectable()
export class BannerService {
constructor(private http: HttpClient, private readonly apollo: Apollo) {}
load(page: number, pageSize: number): Observable<NewsPost[]> {
const startIndex = ((page - 1) % TOTAL_PAGES) * pageSize;
return this.http
.get<NewsPost[]>('assets/data/news.json')
.pipe(
map(news => news.splice(startIndex, pageSize)),
delay(1500),
);
}
constructor(private readonly apollo: Apollo) {}
listBanners(): Observable<any> {
return this.apollo

View file

@ -5,6 +5,7 @@ export class Category {
name!: string;
createdAt!: Date;
updatedAt!: Date | null;
icon?: string | null;
//Products?: Array<Product>;
SubCategory?: Array<any>; //TODO:
_count?: CategoryCount;

View file

@ -0,0 +1,37 @@
export class Product {
id!: string;
userId!: string;
categoryId!: string;
sub_categoryId!: string;
brandId!: string;
name!: string;
description!: string;
conditionId!: string;
price!: number;
countryId!: string | null;
stateId!: string | null;
cityId!: string | null;
neighbourhoodId!: string | null;
zip_code!: string | null;
createdAt!: Date;
approvedAt!: Date | null;
updatedAt!: Date | null;
isActive!: boolean;
isPromoted!: boolean;
viewCount!: number | null;
//user?: User;
//category?: Category;
//sub_category?: SubCategory;
//brand?: Brand;
//condition?: Condition;
//country?: Country | null;
//state?: State | null;
//city?: City | null;
//neighbourhood?: Neighbourhood | null;
//favorites?: Array<Favorite>;
//comments?: Array<Comment>;
//img_urls?: Array<ProductImg>;
//report?: Report | null;
//shares?: Array<Share>;
//_count?: ProductCount;
}

View file

@ -0,0 +1,23 @@
<mdb-carousel [indicators]="true" [animation]="'fade'">
<mdb-carousel-item>
<img
src="https://assets-portal-cms.olx.com.br/1576x300_38126a593d.webp"
class="d-block w-100"
alt="..."
/>
</mdb-carousel-item>
<mdb-carousel-item>
<img
src="https://assets-portal-cms.olx.com.br/1576x300_267d64821e.webp"
class="d-block w-100"
alt="..."
/>
</mdb-carousel-item>
<mdb-carousel-item>
<img
src="https://assets-portal-cms.olx.com.br/1576x300_cc8d61d4ca.webp"
class="d-block w-100"
alt="..."
/>
</mdb-carousel-item>
</mdb-carousel>

View file

@ -0,0 +1,20 @@
@import '../../../@theme/styles/themes';
@import 'bootstrap/scss/mixins/breakpoints';
@import '@nebular/theme/styles/global/breakpoints';
@include nb-install-component() {
.solar-card nb-card-header {
border: none;
padding-bottom: 0;
}
@include media-breakpoint-down(sm) {
ngx-traffic {
display: none;
}
}
}
mdb-carousel-item {
height: 320px;
}

View file

@ -0,0 +1,30 @@
import {Component, OnDestroy, OnInit} from '@angular/core';
import { Subject } from 'rxjs';
import { Banner } from '../../../admin/banner/banner.model';
interface CardSettings {
title: string;
iconClass: string;
type: string;
}
@Component({
selector: 'ngx-home-banner',
styleUrls: ['./banner.component.scss'],
templateUrl: './banner.component.html',
})
export class BannerHomeComponent implements OnInit, OnDestroy {
private destroy$: Subject<void> = new Subject<void>();
banners: Banner[];
constructor() {}
ngOnInit(): void {
console.log('init');
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}

View file

@ -1,3 +1,35 @@
<div class="row">
Home
<div class="col-12">
<ngx-home-banner></ngx-home-banner>
</div>
<div class="col-12">
<div class="category">
<a href="" *ngFor="let category of categories">
<div class="text-container">
<nb-icon [icon]="category.icon" pack="eva"></nb-icon>
<span class="title">{{category.name}}</span>
<i class="line"></i>
</div>
</a>
</div>
<div class="col-12 ad-row">
<div class="ad-container">
<div class="ad"><p>Publicidade</p></div>
</div>
</div>
<div class="col-12">
<div class="d-flex flex-col">
<h2>Anúncios patrocinados</h2>
</div>
<div class="d-flex flex-row flex-nowrap overflow-auto">
<div *ngFor="let product of products" class="card-col">
<ngx-home-product></ngx-home-product>
</div>
</div>
</div>
</div>

View file

@ -1,6 +1,6 @@
@import '../../@theme/styles/themes';
@import 'bootstrap/scss/mixins/breakpoints';
@import '@nebular/theme/styles/global/breakpoints';
@import "../../@theme/styles/themes";
@import "bootstrap/scss/mixins/breakpoints";
@import "@nebular/theme/styles/global/breakpoints";
@include nb-install-component() {
.solar-card nb-card-header {
@ -14,3 +14,145 @@
}
}
}
mdb-carousel-item {
height: 320px;
}
.row .col-12 {
margin-bottom: 20px;
}
@media (min-width: 1280px) {
.category
[_nghost-pwx-c109]
.settings-column[_ngcontent-pwx-c109]
ngd-page-tabs[_ngcontent-pwx-c109] {
margin-bottom: 1.5rem;
}
}
.category {
display: flex;
flex-wrap: wrap;
overflow: hidden;
max-width: 100%;
-webkit-flex-wrap: wrap;
height: 130px;
}
.category a {
display: flex;
flex: 1;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 1rem;
min-width: 120px;
height: 7.5rem;
font-size: 0.875rem;
text-decoration: none;
color: #8994a3;
margin-bottom: 1rem;
background: white;
color: #000000e0;
box-shadow: 0 8px 20px #dae0eb99;
margin-left: 10px;
margin-right: 10px;
}
.category a {
color: #36f;
text-decoration: none;
font-size: inherit;
font-style: inherit;
font-weight: inherit;
line-height: inherit;
}
.category a .text-container {
display: flex;
flex-direction: column;
align-items: center;
}
.category a nb-icon {
font-size: 1.875rem;
margin-bottom: 1rem;
}
.category nb-icon {
font-size: 1.25rem;
line-height: 1;
width: 1em;
height: 1em;
display: inline-block;
}
.category a .title {
padding-bottom: 0.75rem;
font-weight: 500;
text-align: center;
}
.category a .line {
display: none;
height: 0.1875rem;
width: 60%;
background: #3366ff;
border-radius: 1.5px;
}
.category a:hover .line {
display: block;
}
.ad-row {
display: flex;
justify-content: center;
}
.ad-container {
display: flex;
justify-content: center;
width: 970px;
height: 90px;
margin: 24px 12px;
border: 1px gray;
}
.ad {
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
background-color: #e1e1e1;
}
.ad p {
position: absolute;
width: 100px;
text-align: center;
}
.card-col {
flex: 1 0 calc(16.66% - 1rem);
margin: 0 0.5rem;
}
@media screen and (min-width: 1500px) {
.card-col {
flex: 0 0 calc(16.66% - 1rem);
}
}
@media screen and (min-width: 1200px) {
.card-col {
flex: 0 0 calc(20% - 1rem);
}
}
@media screen and (min-width: 840px) {
.card-col {
flex: 0 0 calc(16.66% - 1rem);
}
}

View file

@ -2,6 +2,10 @@ import {Component, OnDestroy} from '@angular/core';
import { NbThemeService } from '@nebular/theme';
import { takeWhile } from 'rxjs/operators' ;
import { SolarData } from '../../@core/data/solar';
import { Banner } from '../../admin/banner/banner.model';
import { Subject } from 'rxjs';
import { Category } from '../../admin/category/category.model';
import { Product } from '../../admin/product/product';
interface CardSettings {
title: string;
@ -15,85 +19,108 @@ interface CardSettings {
templateUrl: './home.component.html',
})
export class HomeComponent implements OnDestroy {
private destroy$: Subject<void> = new Subject<void>();
banners: Banner[];
categories: Category[];
products: any[];
private alive = true;
constructor() {}
solarValue: number;
lightCard: CardSettings = {
title: 'Light',
iconClass: 'nb-lightbulb',
type: 'primary',
};
rollerShadesCard: CardSettings = {
title: 'Roller Shades',
iconClass: 'nb-roller-shades',
type: 'success',
};
wirelessAudioCard: CardSettings = {
title: 'Wireless Audio',
iconClass: 'nb-audio',
type: 'info',
};
coffeeMakerCard: CardSettings = {
title: 'Coffee Maker',
iconClass: 'nb-coffee-maker',
type: 'warning',
};
ngOnInit(): void {
console.log('init');
statusCards: string;
commonStatusCardsSet: CardSettings[] = [
this.lightCard,
this.rollerShadesCard,
this.wirelessAudioCard,
this.coffeeMakerCard,
];
statusCardsByThemes: {
default: CardSettings[];
cosmic: CardSettings[];
corporate: CardSettings[];
dark: CardSettings[];
} = {
default: this.commonStatusCardsSet,
cosmic: this.commonStatusCardsSet,
corporate: [
this.categories = [
{
...this.lightCard,
type: 'warning',
"name": "Nutrientes",
"id": "Nutrientes",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "arrow-ios-back-outline"
},
{
...this.rollerShadesCard,
type: 'primary',
"name": "Iluminação",
"id": "Decoração",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "bulb-outline"
},
{
...this.wirelessAudioCard,
type: 'danger',
"name": "Hidroponia",
"id": "Hidroponia",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "droplet-outline"
},
{
...this.coffeeMakerCard,
type: 'info',
"name": "Irrigação",
"id": "Irrigação",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "arrow-ios-back-outline"
},
],
dark: this.commonStatusCardsSet,
};
{
"name": "Colheita",
"id": "Colheita",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "arrow-ios-back-outline"
},
{
"name": "Pragas",
"id": "Pragas",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "arrow-ios-back-outline"
},
{
"name": "Potes e Vasos",
"id": "Potes e Vasos",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "arrow-ios-back-outline"
},
{
"name": "Substratos",
"id": "Substratos",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "arrow-ios-back-outline"
},
{
"name": "Controle",
"id": "Controle",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "arrow-ios-back-outline"
},
{
"name": "Clonagem",
"id": "Clonagem",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "copy-outline"
},
{
"name": "Tendas",
"id": "Tendas",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "arrow-ios-back-outline"
},
{
"name": "Circulação",
"id": "Circulação",
"updatedAt": new Date(),
"createdAt": new Date(),
"icon": "arrow-ios-back-outline"
},
]
constructor(private themeService: NbThemeService,
private solarService: SolarData) {
this.themeService.getJsTheme()
.pipe(takeWhile(() => this.alive))
.subscribe(theme => {
this.statusCards = this.statusCardsByThemes[theme.name];
});
this.solarService.getSolarData()
.pipe(takeWhile(() => this.alive))
.subscribe((data) => {
this.solarValue = data;
});
this.products = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
}
ngOnDestroy() {
this.alive = false;
this.destroy$.next();
this.destroy$.complete();
}
}

View file

@ -1,4 +1,4 @@
import { NgModule } from '@angular/core';
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import {
NbActionsModule,
NbButtonModule,
@ -15,6 +15,9 @@ import { NgxEchartsModule } from 'ngx-echarts';
import { ThemeModule } from '../../@theme/theme.module';
import { HomeComponent } from './home.component';
import { FormsModule } from '@angular/forms';
import { MdbCarouselModule } from 'mdb-angular-ui-kit/carousel';
import { BannerHomeComponent } from './banner/banner.component';
import { ProductHomeComponent } from './product/product.component';
@NgModule({
imports: [
@ -31,9 +34,13 @@ import { FormsModule } from '@angular/forms';
NbIconModule,
NbButtonModule,
NgxEchartsModule,
MdbCarouselModule
],
declarations: [
HomeComponent
HomeComponent,
BannerHomeComponent,
ProductHomeComponent
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class HomeModule { }

View file

@ -0,0 +1,23 @@
<nb-card>
<nb-card-header class="card-img-top">
<ul>
<li>
<img src="https://img.olx.com.br/images/89/890461810585731.webp" />
</li>
</ul>
<span class="badge">Destaque</span>
</nb-card-header>
<nb-card-body>
<h5 class="card-title">Bioledz 38400 - 800 watts</h5>
<p class="card-text">R$ 3.475,99</p>
</nb-card-body>
<ul class="list-group list-group-flush">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
</ul>
<nb-card-footer>
<a href="#" class="card-link">Ver</a>
</nb-card-footer>
</nb-card>

View file

@ -0,0 +1,75 @@
@import '../../../@theme/styles/themes';
@import 'bootstrap/scss/mixins/breakpoints';
@import '@nebular/theme/styles/global/breakpoints';
.card-img-top {
font-size: 1.125rem;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
text-anchor: middle;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
overflow: hidden;
border-bottom: 0;
height: 180px;
padding: 0;
position: relative;
}
.card-img-top ul {
align-items: center;
display: flex;
height: 100%;
justify-content: flex-start;
margin: 0;
overflow: scroll hidden;
padding: 0;
scroll-snap-type: x mandatory;
scrollbar-width: none;
pointer-events: auto;
}
.card-img-top ul li {
align-items: center;
display: flex;
height: 100%;
justify-content: center;
list-style: none;
margin: 0;
min-width: 100%;
overflow: hidden;
padding: 0;
position: relative;
scroll-snap-align: start;
scroll-snap-stop: always;
}
.card-img-top ul li img, .card-img-top ul li svg {
width: 100%;
height: 100%;
display: block;
object-fit: cover;
overflow-clip-margin: content-box;
overflow: clip;
}
.card-img-top span.badge {
align-items: center;
background: blue;
color:white;
font-weight: 600;
overflow: hidden;
white-space: nowrap;
border-radius: 4px;
font-size: 12px;
height: 24px;
left: 16px;
top: 16px;
max-width: calc(100% - 16px);
position: absolute;
z-index: 8;
display: block;
text-overflow: ellipsis;
padding: 4px 8px;
}

View file

@ -0,0 +1,24 @@
import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import { Subject } from 'rxjs';
import { Product } from '../../../admin/product/product';
@Component({
selector: 'ngx-home-product',
styleUrls: ['./product.component.scss'],
templateUrl: './product.component.html',
})
export class ProductHomeComponent implements OnInit, OnDestroy {
private destroy$: Subject<void> = new Subject<void>();
@Input() product: Product;
constructor() {}
ngOnInit(): void {
console.log('init');
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
}

View file

@ -5,12 +5,14 @@ import { ThemeModule } from '../@theme/theme.module';
import { PublicComponent } from './public.component';
import { PublicRoutingModule } from './public-routing.module';
import { MiscellaneousModule } from './miscellaneous/miscellaneous.module';
import { HomeModule } from './home/home.module';
@NgModule({
imports: [
PublicRoutingModule,
ThemeModule,
NbMenuModule,
MiscellaneousModule
MiscellaneousModule,
HomeModule
],
declarations: [
PublicComponent,

View file

@ -9,6 +9,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/png" href="favicon.png">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
<script defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCpVhQiwAllg1RAFaxMWSpQruuGARy0Y1k&libraries=places"></script>
</head>
<body>