Starting work on BioTrivia, fixed some styles

This commit is contained in:
Kaloian Venkov 2021-03-12 15:19:46 +02:00
parent 500d1ad996
commit 792e38668c
39 changed files with 455 additions and 52 deletions

View File

@ -0,0 +1,24 @@
import { animate, animateChild, group, query, style, transition, trigger } from "@angular/animations";
export const slideInAnimation =
trigger('routeAnimations', [
transition('* <=> *', [
style({ position: 'relative' }),
query(':enter', [
style({ opacity: 0, position: 'absolute', top: 0, left: 0, width: '100%' })
], { optional: true }),
query(':leave', [
style({ opacity: 1 })
], { optional: true }),
query(':leave', animateChild(), { optional: true }),
group([
query(':leave', [
animate('300ms ease-out', style({ opacity: 0 }))
], { optional: true }),
query(':enter', [
animate('300ms ease-out', style({ opacity: 1 }))
], { optional: true })
]),
query(':enter', animateChild(), { optional: true }),
]),
]);

View File

@ -4,8 +4,9 @@ import { DashboardComponent } from './dashboard/dashboard.component';
import { MinigameConveyorRecyclingComponent } from './minigame-conveyor-recycling/minigame-conveyor-recycling.component'; import { MinigameConveyorRecyclingComponent } from './minigame-conveyor-recycling/minigame-conveyor-recycling.component';
const routes: Routes = [ const routes: Routes = [
{ path: 'minigames/conveyor-belt', component: MinigameConveyorRecyclingComponent }, { path: 'minigames/conveyor-belt', component: MinigameConveyorRecyclingComponent, data: { animation: 'conveyor-belt-mg' } },
{ path: '', component: DashboardComponent }, { path: 'minigames/biotrivia', component: MinigameConveyorRecyclingComponent, data: { animation: 'biotrinia-mg' } },
{ path: '', component: DashboardComponent, data: { animation: 'home' } },
]; ];
@NgModule({ @NgModule({

View File

@ -1 +1,3 @@
<router-outlet></router-outlet> <div [@routeAnimations]="prepareRoute(outlet)">
<router-outlet #outlet="outlet" style="display: none;"></router-outlet>
</div>

View File

@ -1,10 +1,15 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { IgxIconService } from 'igniteui-angular'; import { IgxIconService } from 'igniteui-angular';
import { slideInAnimation } from './animations';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'] styleUrls: ['./app.component.scss'],
animations: [
slideInAnimation,
]
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit {
title = 'apollo-frontend'; title = 'apollo-frontend';
@ -16,5 +21,8 @@ export class AppComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
this.icons.addSvgIcon('danger', '/assets/icons/risk-skull.svg'); this.icons.addSvgIcon('danger', '/assets/icons/risk-skull.svg');
} }
prepareRoute(outlet: RouterOutlet): void {
return outlet && outlet.activatedRouteData && outlet.activatedRouteData.animation;
}
} }

View File

@ -16,6 +16,7 @@ import { DashboardComponent } from './dashboard/dashboard.component';
import { DashboardMinigamesComponent } from './dashboard-minigames/dashboard-minigames.component'; import { DashboardMinigamesComponent } from './dashboard-minigames/dashboard-minigames.component';
import { MinigameCardComponent } from './minigame-card/minigame-card.component'; import { MinigameCardComponent } from './minigame-card/minigame-card.component';
import { MinigameConveyorRecyclingComponent } from './minigame-conveyor-recycling/minigame-conveyor-recycling.component'; import { MinigameConveyorRecyclingComponent } from './minigame-conveyor-recycling/minigame-conveyor-recycling.component';
import { MinigameBiotriviaComponent } from './minigame-biotrivia/minigame-biotrivia.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -26,6 +27,7 @@ import { MinigameConveyorRecyclingComponent } from './minigame-conveyor-recyclin
DashboardMinigamesComponent, DashboardMinigamesComponent,
MinigameCardComponent, MinigameCardComponent,
MinigameConveyorRecyclingComponent, MinigameConveyorRecyclingComponent,
MinigameBiotriviaComponent,
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@ -4,18 +4,18 @@
<div [class]="[type, 'icon']" *ngIf="type !== 'normal'"></div> <div [class]="[type, 'icon']" *ngIf="type !== 'normal'"></div>
</div> </div>
</div> </div>
<div class="main"> <div class="main" *ngIf="!flipped">
<div class="contents" #frontSide *ngIf="!flipped"> <div class="contents" #frontSide>
<h6>{{card.name}}</h6> <h6>{{card.name}}</h6>
<div class="img-fitter" [style.background-image]="'url(\'' + card.imageUrl + '\')'"> <div class="img-fitter" [style.background-image]="'url(\'' + card.imageUrl + '\')'">
</div> </div>
</div> </div>
<div class="contents" #backSide *ngIf="flipped"> </div>
<div class="info" #backSide *ngIf="flipped">
<div class="contents" *ngFor="let paragraph of card.info"> <div class="contents" *ngFor="let paragraph of card.info">
<h6 class="small">{{paragraph.heading}}</h6> <h6 class="small">{{paragraph.heading}}</h6>
<p class="small">{{paragraph.content}}</p> <p class="small">{{paragraph.content}}</p>
</div> </div>
</div> </div>
</div>
<button igxButton igxRipple (click)="flip()">Обърни</button> <button igxButton igxRipple (click)="flip()">Обърни</button>
</div> </div>

View File

@ -3,30 +3,14 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
box-sizing: border-box; box-sizing: border-box;
flex: 1 0 auto; flex: 1 1 auto;
align-items: flex-start;
&>* { &>* {
flex: 1 0 auto; flex: 1 0 auto;
} }
h6 { h6 {
margin: 0; margin: 0;
text-align: center; text-align: center;
&.small {
margin-top: .5em;
}
}
p {
margin: 0;
&.small::before {
content: '';
width: 2em;
height: 3px;
display: inline-block;
}
}
.small {
font-size: .75em;
line-height: 1em;
text-align: start;
} }
.img-fitter{ .img-fitter{
margin-top: .5em; margin-top: .5em;
@ -35,6 +19,8 @@
flex: 1 0 auto; flex: 1 0 auto;
background: center no-repeat; background: center no-repeat;
background-size: cover; background-size: cover;
box-shadow: transparent 3px 3px 5px;
position: relative;
} }
margin-top: .5em; margin-top: .5em;
@ -60,6 +46,32 @@
} }
} }
} }
.info {
overflow: auto;
flex: 1 1 auto;
p {
margin: 0;
&.small::before {
content: '';
width: 2em;
height: 3px;
display: inline-block;
}
}
h6 {
margin: 0;
text-align: center;
&.small {
margin-bottom: .25em;
margin-top: .5em;
}
}
.small {
font-size: .75em;
line-height: 1.25em;
text-align: start;
}
}
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -72,7 +84,8 @@
box-shadow: #0004 3px 3px 5px; box-shadow: #0004 3px 3px 5px;
background-color: #f8f8f8; background-color: #f8f8f855;
backdrop-filter: blur(10px);
button { button {
margin: 0 auto; margin: 0 auto;

View File

@ -1,5 +1,8 @@
<h4 style="margin-bottom: 1em; text-align: center;">Вашите карти:</h4> <h4 style="margin-bottom: 1em; text-align: center;">Вашите карти:</h4>
<div class="cards"> <div class="cards">
<app-card [card]="{ name: 'test', imageUrl: 'no-image', types: [ 'normal' ], info: [] }"></app-card> <div class="cards-inner">
<app-card></app-card> <div class="contnets" *ngFor="let card of getCards()" class="card">
<app-card [card]="card"></app-card>
</div>
</div>
</div> </div>

View File

@ -1,4 +1,18 @@
.cards { .cards {
display: flex; width: 100%;
gap: 2em; height: 332px;
overflow-y: auto;
overflow-x: hidden;
scroll-snap-type: y mandatory;
}
.cards-inner {
display: flex;
flex-wrap: wrap;
width: 100%;
gap: 2em;
padding: 1em 0;
box-sizing: border-box;
}
.card {
scroll-snap-align: start;
} }

View File

@ -1,4 +1,6 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Card, DbService } from '../db.service';
import { UserdataService } from '../userdata.service';
@Component({ @Component({
selector: 'app-dashboard-cards', selector: 'app-dashboard-cards',
@ -7,9 +9,15 @@ import { Component, OnInit } from '@angular/core';
}) })
export class DashboardCardsComponent implements OnInit { export class DashboardCardsComponent implements OnInit {
constructor() { } constructor(
private db: DbService,
) { }
ngOnInit(): void { ngOnInit(): void {
} }
getCards(): Card[] {
return this.db.getAllCards().map(v => v.el);
}
} }

View File

@ -1,5 +1,7 @@
<h4 style="margin-bottom: 1em; text-align: center;">Миниигри:</h4> <h4 style="text-align: center;">Миниигри:</h4>
<div class="cards"> <div class="cards">
<app-minigame-card *ngFor="let minigame of getMinigames()" <div class="cards-inner">
<app-minigame-card *ngFor="let minigame of getMinigames()" class="card"
[minigame]="minigame.el" [minigameUserdata]="getMinigameUserdata(minigame.id)"></app-minigame-card> [minigame]="minigame.el" [minigameUserdata]="getMinigameUserdata(minigame.id)"></app-minigame-card>
</div>
</div> </div>

View File

@ -1,4 +1,18 @@
.cards { .cards {
display: flex; width: 100%;
gap: 2em; height: 232px;
overflow-y: auto;
overflow-x: hidden;
}
.cards-inner {
display: flex;
flex-wrap: wrap;
width: 100%;
gap: 2em;
padding: 1em 0;
scroll-snap-type: y mandatory;
box-sizing: border-box;
}
.card {
scroll-snap-align: start;
} }

View File

@ -1,2 +1,4 @@
<app-dashboard-minigames></app-dashboard-minigames> <div class="a">
<app-dashboard-cards></app-dashboard-cards> <app-dashboard-minigames></app-dashboard-minigames>
<app-dashboard-cards></app-dashboard-cards>
</div>

View File

@ -0,0 +1,4 @@
.a {
display: flex;
flex-direction: column;
}

View File

@ -3,6 +3,7 @@ import { Injectable } from '@angular/core';
export interface Minigame { export interface Minigame {
name: string; name: string;
url: string; url: string;
comingSoon?: boolean;
} }
export interface CardParagraph { export interface CardParagraph {
@ -28,12 +29,274 @@ export class DbService {
{ {
id: '0', id: '0',
el: { el: {
name: 'Convayer Recycling', name: 'Рециклиране',
url: '/minigames/conveyor-belt', url: '/minigames/conveyor-belt',
} }
},
{
id: '0',
el: {
name: 'BioTrivia',
url: '/minigames/biotrivia',
}
} }
]; ];
private mock_card_types: Saved<Card>[]; private mock_card_types: Saved<Card>[] = [
{
id: '0',
el: {
name: 'Пингвин',
types: ['normal'],
imageUrl: '/assets/images/cards/pingvin.jpg',
info: [
{
content: 'Тъй като нямат естествен враг на сушата, пингвините не показват страх, а любопитство когато към тях се приближи човек.',
heading: 'Интересно'
}
]
}
},
{
id: '1',
el: {
name: 'Пингвин',
types: ['normal'],
imageUrl: '/assets/images/cards/pingvin2.jpg',
info: [
{
content: 'Пингвините мътят яйцата си на смени. Когато мъжкият отиде да яде, той не може да намери пътя обратно към гнездото и започва да крещи шумно. Женските разпознават гласовете на партньорите си сред хиляди други и крещят в отговор, така че те да знаят къде да се върнат.',
heading: 'Интересно'
}
]
}
},
{
id: '2',
el: {
name: 'Делфин',
types: ['normal'],
imageUrl: '/assets/images/cards/delfin.jpg',
info: [
{
content: 'Делфините общуват по между си с помощта на звуци, като всеки звук може да изразява различно настроение.',
heading: 'Интересно'
}
]
}
},
{
id: '3',
el: {
name: 'Делфин',
types: ['normal'],
imageUrl: '/assets/images/cards/delfin2.jpg',
info: [
{
content: 'Делфините никога не заспиват напълно. Докато си почиват, едната половина на мозъка им продължава да бъде активна. Ето защо дори и по време на сън едното им око остава отворено.',
heading: 'Интересно'
}
]
},
},
{
id: '4',
el: {
name: 'Син кит',
types: ['normal'],
imageUrl: '/assets/images/cards/sinkit.jpg',
info: [
{
content: 'Освен най-едрото, синият кит е и най-шумното животно звукът, който издава е от порядъка на 188 децибела и може да бъде чут на разстояние до 800 км. За сравнение, звукът на пътнически самолет е „едва” 120 децибела.',
heading: 'Интересно'
}
]
}
},
{
id: '5',
el: {
name: 'Син кит',
types: ['normal'],
imageUrl: '/assets/images/cards/sinkit2.jpg',
info: [
{
content: 'Езикът на кита тежи около 4,7 тона. (почти колкото митко и майка му)',
heading: 'Интересно'
}
]
}
},
{
id: '6',
el: {
name: 'Пор',
types: ['endangered'],
imageUrl: '/assets/images/cards/por.jpg',
info: [
{
heading: 'Морфология на "пор"',
content: 'Думата "пор" произлиза от латински и означава "крадец".',
},
{
heading: 'Застрашен вид',
content: 'Загубата на местообитания и бракониерството, са причина днес те или техните следи да се наблюдават изключително рядко.',
},
],
},
},
{
id: '7',
el: {
name: 'Кафява мечка',
types: ['endangered'],
imageUrl: '/assets/images/cards/kafqva-mechka.jpg',
info: [
{
heading: 'Сладки сънища',
content: 'Учените вярват, че мечките могат да сънуват.',
},
{
heading: 'Fast as f',
content: 'Макар да изглеждат тромави,мечките могат да тичат с до 60 км/ч.',
},
{
heading: 'Застрашен вид',
content: 'За съжаление хората им нанасят непоправими щети, като разкъсват с пътища и огради ареала им, унищожават горите и ги избиват.',
},
],
},
},
{
id: '8',
el: {
name: 'Балканска дива коза',
types: ['endangered'],
imageUrl: '/assets/images/cards/koza.jpg',
info: [
{
heading: 'Властелина на пръстените',
content: 'Знаехте ли, че всяка година се прибавя по още един пръстен върху рогата на дивата коза, като така може да се определи възрастта на даденото животно.',
},
{
heading: 'И ся почваме да бегами',
content: 'На света няма друго животно, което да притежава по-голяма ловкост и бързина на придвижване по хлъзгави и стръмни терени.',
},
],
},
},
{
id: '9',
el: {
name: 'Прилеп',
types: ['endangered'],
imageUrl: '/assets/images/cards/prilep.jpg',
info: [
{
heading: 'Напаст пещерна',
content: 'най-голямата колония от прилепи в света наброява над 20 милиона броя от тези летящи създания.',
},
{
heading: 'Ехо .... (ехо)',
content: 'Прилепите използват ехолокация, за да се заобиколят в тъмното.',
},
{
heading: 'Защитен вид',
content: 'Според българското законодателство, прилепите са защитени видове.',
},
],
},
},
{
id: '10',
el: {
name: 'Лалугер',
types: ['endangered'],
imageUrl: '/assets/images/cards/laluger.jpg',
info: [
{
heading: 'Втори братовчед на ленивеца',
content: 'Когато е студено, той заспива зимен сън и се събужда едва през пролетта.',
},
{
heading: 'Мали ша са напикая',
content: 'Когато е изплашен, той застава на задните си лапи.',
},
{
heading: 'Защитен вид',
content: 'Интензивно селско стопанство и използване на пестициди причиняват бързото изчезване на този вид.',
},
],
},
},
{
id: '11',
el: {
name: 'Етруската земеровка',
types: ['endangered'],
imageUrl: '/assets/images/cards/zemerovka.jpg',
info: [
{
heading: 'Размер',
content: 'Един от най-дребните бозайници на планетата с размери едва 3,6 до 5,2 см и тегло от 1,25 до 2,34 грама!',
},
{
heading: 'Лакомници',
content: 'Етруската земеровка трява да яде непрекъснато за да може да живее.',
},
],
},
},
{
id: '12',
el: {
name: 'Тюленът монах',
types: ['endangered'],
imageUrl: '/assets/images/cards/tuleni.jpg',
info: [
{
heading: 'Техния живот',
content: 'Те се крият в подводни пещери, където си почиват и раждат своите малки.',
},
],
},
},
{
id: '13',
el: {
name: 'Видра',
types: ['endangered'],
imageUrl: '/assets/images/cards/vidra.jpg',
info: [
{
heading: 'Мали колко сладко',
content: 'Морските видри се държат за ръце докато спят, за да не бъдат разделени от теченията докато се носят по водната повърхност.',
},
{
heading: 'NO MERCY',
content: 'В момент на опасност видрите показват бебетата си на хищниците, за да предизвикат съчувствие и по този начин да избегнат атаката.',
},
],
},
},
{
id: '14',
el: {
name: 'Ловен сокол',
types: ['endangered'],
imageUrl: '/assets/images/cards/sokol.jpg',
info: [
{
heading: 'Ловни навици',
content: 'Те не ловуват близо до гнездата си, а се опитват да летят доколкото е възможно.',
},
{
heading: 'Застрашен вид',
content: 'Има опасност от изчезване. Основната причина, поради която населението на ловния сокол намалява, е човешката дейност.',
},
],
},
},
];
private getRandomEl<T>(array: T[]): T { private getRandomEl<T>(array: T[]): T {
const index = Math.floor(Math.random() * array.length); const index = Math.floor(Math.random() * array.length);

View File

@ -0,0 +1 @@
<p>minigame-biotrivia works!</p>

View File

@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MinigameBiotriviaComponent } from './minigame-biotrivia.component';
describe('MinigameBiotriviaComponent', () => {
let component: MinigameBiotriviaComponent;
let fixture: ComponentFixture<MinigameBiotriviaComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MinigameBiotriviaComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(MinigameBiotriviaComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-minigame-biotrivia',
templateUrl: './minigame-biotrivia.component.html',
styleUrls: ['./minigame-biotrivia.component.scss']
})
export class MinigameBiotriviaComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -51,7 +51,8 @@
box-shadow: #0004 3px 3px 5px; box-shadow: #0004 3px 3px 5px;
background-color: #f8f8f8; background-color: #f8f8f855;
backdrop-filter: blur(10px);
button { button {
margin: 0 auto; margin: 0 auto;

View File

@ -1,3 +0,0 @@
<canvas class="canvas">
</canvas>

View File

@ -54,7 +54,9 @@ export class UserdataService {
} }
} }
getOwnedCards(): Card[] { getOwnedCards(): Card[] {
return this.getOwnedCardIds().map(v => this.db.getCard(v)); return this.getOwnedCardIds().map(v => {
return this.db.getCard(v);
});
} }
saveMinigameUserdata(id: string, userdata: MinigameUserdata): void { saveMinigameUserdata(id: string, userdata: MinigameUserdata): void {

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,11 +1,15 @@
/* You can add global styles to this file, and also import other style files */ /* You can add global styles to this file, and also import other style files */
body, html { body,
html {
padding: 0; padding: 0;
margin: 0; margin: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-image: url('/assets/images/Forest BG.png');
background-size: cover
} }
// Uncomment the following lines if you want to add a custom palette: // Uncomment the following lines if you want to add a custom palette:
// $primary: #731963 !default; // $primary: #731963 !default;
// $secondary: #ce5712 !default; // $secondary: #ce5712 !default;
@ -18,10 +22,8 @@ body, html {
$company-color: rgb(139, 39, 39); // Some green shade I like $company-color: rgb(139, 39, 39); // Some green shade I like
$secondary-color: rgb(139, 39, 39); // Watermelon pink $secondary-color: rgb(139, 39, 39); // Watermelon pink
$my-color-palette: igx-palette( $my-color-palette: igx-palette($primary: $company-color,
$primary: $company-color, $secondary: $secondary-color);
$secondary: $secondary-color
);
@include igx-core(); @include igx-core();
@include igx-theme($my-color-palette); @include igx-theme($my-color-palette);