Compare commits

...

19 Commits

Author SHA1 Message Date
219f6ee46b Jenkins en docker ?! 2025-01-11 01:25:31 +01:00
826da5440c Jenkins en docker ?! 2025-01-11 01:23:46 +01:00
438917cf3c #fuckit 2025-01-09 21:33:06 +01:00
41cab0b660 #fuckit 2025-01-09 21:02:05 +01:00
b7e6399102 Docker toegevoegd aan pipeline 2025-01-05 20:51:29 +01:00
b10a704c85 Docker toegevoegd aan pipeline 2025-01-05 20:49:22 +01:00
a4df3f78a6 Jenkinsfile aangepast 2025-01-05 20:43:27 +01:00
591bf3a354 GITURL aangepast
Some checks failed
Docker Image CI / build-and-push (push) Has been cancelled
Docker Image CI / deploy (push) Has been cancelled
2025-01-05 20:28:40 +01:00
Mel Van Veen
9b1eb91e3e test commit
Some checks are pending
Docker Image CI / build-and-push (push) Waiting to run
Docker Image CI / deploy (push) Blocked by required conditions
2025-01-05 20:19:53 +01:00
Mel M. van Veen
7a6b3bb394 versie 1.4.1 - n8n test
Some checks are pending
Docker Image CI / build-and-push (push) Waiting to run
Docker Image CI / deploy (push) Blocked by required conditions
2024-12-03 19:45:53 +01:00
Mel M. van Veen
1afb06beed versie 1.4.0 - the 'Me 'n U' update 2024-12-03 16:05:22 +01:00
Mel M. van Veen
198b433ceb versie 1.3.1 - bug fixes 2024-12-03 14:08:42 +01:00
Mel M. van Veen
f34ca26cdd versie 1.3.0 - the 'feel' update 2024-12-03 13:57:29 +01:00
Mel M. van Veen
83ce734c82 v1.2.3 - final git actions pipeline fix 2024-12-03 10:13:01 +01:00
Mel van Veen
507726061d Update docker-image.yml 2024-12-03 10:08:48 +01:00
Mel van Veen
b0d8b66765 Update docker-image.yml 2024-12-03 09:59:22 +01:00
Mel van Veen
9ce3d1303b Update docker-image.yml 2024-12-03 09:54:47 +01:00
Mel van Veen
e34e82af6b Update docker-image.yml 2024-12-03 09:49:22 +01:00
Mel van Veen
9af54e9671 Update docker-image.yml 2024-12-03 09:48:44 +01:00
32 changed files with 903 additions and 215 deletions

View File

@@ -6,9 +6,6 @@ on:
pull_request:
branches: [ "main" ]
env:
VERSION: "$(cat package.json | jq -r '.version')"
jobs:
build-and-push:
runs-on: ubuntu-latest
@@ -17,10 +14,15 @@ jobs:
# Stap 1: Code ophalen
- uses: actions/checkout@v4
# Stap 2: Versienummer ophalen uit package.json
# Stap 2: Versienummer ophalen uit package.json en opslaan als artifact
- name: Extract Angular version
id: get_version
run: echo "VERSION=$(cat package.json | jq -r '.version')" >> $GITHUB_ENV
run: |
echo "$(cat package.json | jq -r '.version')" > version.txt
- name: Save version as artifact
uses: actions/upload-artifact@v3
with:
name: version
path: version.txt
# Stap 3: Inloggen bij Docker Hub
- name: Log in to Docker Hub
@@ -31,11 +33,15 @@ jobs:
# Stap 4: Docker-image bouwen en taggen met Angular-versie
- name: Build the Docker image
run: docker build . --file Dockerfile --tag veenm/weetikveel:${{ env.VERSION }} --tag veenm/weetikveel:latest
run: |
VERSION=$(cat version.txt)
docker build . --file Dockerfile --tag veenm/weetikveel:$VERSION --tag veenm/weetikveel:latest
# Stap 5: Docker-image pushen naar Docker Hub (huidige versie tag)
- name: Push the Docker image (version)
run: docker push veenm/weetikveel:${{ env.VERSION }}
run: |
VERSION=$(cat version.txt)
docker push veenm/weetikveel:$VERSION
# Stap 6: Docker-image pushen naar Docker Hub (latest tag)
- name: Push the Docker image (latest)
@@ -46,10 +52,18 @@ jobs:
runs-on: ubuntu-latest
steps:
# Stap 1: Artifact ophalen
- name: Download version artifact
uses: actions/download-artifact@v3
with:
name: version
- name: Use Variable
run: echo "${{ env.VERSION }}"
# Stap 1: Maak verbinding via SSH naar de TrueNAS SCALE server
# Stap 2: Lees versie uit het artifact
- name: Read version
id: read_version
run: echo "VERSION=$(cat version.txt)" >> $GITHUB_ENV
# Stap 3: Maak verbinding via SSH naar de TrueNAS SCALE server
- name: SSH into TrueNAS SCALE
uses: appleboy/ssh-action@v0.1.10
with:
@@ -58,18 +72,21 @@ jobs:
password: ${{ secrets.TRUENAS_PASSWORD }}
port: ${{ secrets.TRUENAS_PORT }}
script: |
# Stap 2: K3s Kubernetes-configuratie instellen
VERSION=${{ env.VERSION }}
echo "Gekozen versie: $VERSION"
# Kubernetes-configuratie instellen
export KUBEVERSION=/etc/rancher/k3s/k3s.yaml
export KUBECONFIG=$KUBEVERSION
# Update deployment
k3s kubectl apply -f deployment.yaml
k3s kubectl apply -f service.yaml
# Stap 4: Update de Kubernetes deployment (optioneel, vervang bestaande image)
k3s kubectl set image deployment/weetikveel weetikveel=veenm/weetikveel:${{ env.VERSION }} --record
# Update image in deployment
k3s kubectl set image deployment/weetikveel weetikveel=veenm/weetikveel:${VERSION} --record
# Stap 5: Controleer de status van de pods en services
# Controle en status
k3s kubectl rollout status deployment/weetikveel
k3s kubectl get pods
k3s kubectl get service

71
Jenkinsfile vendored
View File

@@ -1,10 +1,16 @@
pipeline {
agent any
agent {
dockerfile true
}
tools {
nodejs "nodejs"
}
environment {
DOCKER_IMAGE_NAME = "weetikveel"
DOCKER_REGISTRY = "veenm" // Optioneel als je Docker image naar Docker Hub wilt pushen
TRUENAS_HOST = "77.175.130.12:9000" // IP-adres van TrueNAS
TRUENAS_HOST = "192.168.2.31:9000" // IP-adres van TrueNAS
TRUENAS_SSH_USER = "jenkins" // Gebruiker voor SSH
TRUENAS_SSH_KEY = credentials('ssh-true-nas') // Voeg een SSH-sleutel toe in Jenkins credentials
}
@@ -12,7 +18,7 @@ pipeline {
stages {
stage('Checkout') {
steps {
git 'https://github.com/veenm/weetikveel.git' // Vervang door jouw repository URL
git 'https://git.melvanveen.nl/veenm/weetikveel.git' // Vervang door jouw repository URL
}
}
@@ -26,36 +32,37 @@ pipeline {
}
}
stage('Build Docker Image') {
steps {
script {
// Bouw het Docker image
sh 'docker build -t $DOCKER_IMAGE_NAME .'
}
}
}
// stage('Build Docker Image') {
// steps {
// script {
// // Bouw het Docker image
// sh 'systemctl start docker'
// sh 'docker build -t weetikveel .'
// }
// }
// }
stage('Deploy to TrueNAS') {
steps {
script {
// SSH naar TrueNAS en stop de oude container (indien nodig)
sh """
ssh -i $TRUENAS_SSH_KEY $TRUENAS_SSH_USER@$TRUENAS_HOST 'docker stop $DOCKER_IMAGE_NAME || true && docker rm $DOCKER_IMAGE_NAME || true'
"""
// Push het Docker image naar TrueNAS (optioneel als je een registry gebruikt)
sh 'docker tag $DOCKER_IMAGE_NAME $TRUENAS_HOST/$DOCKER_IMAGE_NAME'
sh 'docker push $TRUENAS_HOST/$DOCKER_IMAGE_NAME' // Alleen als je Docker Hub gebruikt, of een lokaal registry.
// Deploy het Docker image naar TrueNAS via SSH
sh """
ssh -i $TRUENAS_SSH_KEY $TRUENAS_SSH_USER@$TRUENAS_HOST '
docker pull $TRUENAS_HOST/$DOCKER_IMAGE_NAME &&
docker run -d -p 80:80 --name $DOCKER_IMAGE_NAME $TRUENAS_HOST/$DOCKER_IMAGE_NAME
'
"""
}
}
}
// stage('Deploy to TrueNAS') {
// steps {
// script {
// // SSH naar TrueNAS en stop de oude container (indien nodig)
// sh """
// ssh -i $TRUENAS_SSH_KEY $TRUENAS_SSH_USER@$TRUENAS_HOST 'docker stop $DOCKER_IMAGE_NAME || true && docker rm $DOCKER_IMAGE_NAME || true'
// """
// // Push het Docker image naar TrueNAS (optioneel als je een registry gebruikt)
// sh 'docker tag $DOCKER_IMAGE_NAME $TRUENAS_HOST/$DOCKER_IMAGE_NAME'
// sh 'docker push $TRUENAS_HOST/$DOCKER_IMAGE_NAME' // Alleen als je Docker Hub gebruikt, of een lokaal registry.
//
// // Deploy het Docker image naar TrueNAS via SSH
// sh """
// ssh -i $TRUENAS_SSH_KEY $TRUENAS_SSH_USER@$TRUENAS_HOST '
// docker pull $TRUENAS_HOST/$DOCKER_IMAGE_NAME &&
// docker run -d -p 80:80 --name $DOCKER_IMAGE_NAME $TRUENAS_HOST/$DOCKER_IMAGE_NAME
// '
// """
// }
// }
// }
}
post {

View File

@@ -1,6 +1,23 @@
# Wiv
# WeetIkVeel
## Changelog
TEST
### - versie 1.4.0 - the 'Me 'n U' update:
- Menu in spelscherm toegevoegd
- Instellingen toegevoegd
- Mogelijkheid naam aanpassen toegevoegd
### - versie 1.3.1 - bug fixes
- tussenstand scherm fix
### - versie 1.3.0 - the 'feel' update:
- tussenstand scherm toegevoegd
- nieuw lettertype toegevoegd om de 'RTL feel' te geven
- eindstand scherm aangepast
- beginscherm aangepast
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.0.2.
## Development server

6
package-lock.json generated
View File

@@ -1,14 +1,14 @@
{
"name": "wiv",
"version": "1.2.2",
"version": "1.4.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wiv",
"version": "1.2.2",
"version": "1.4.1",
"dependencies": {
"@angular/animations": "^19.0.0",
"@angular/animations": "^19.0.1",
"@angular/cdk": "^19.0.0",
"@angular/common": "^19.0.0",
"@angular/compiler": "^19.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "wiv",
"version": "1.2.2",
"version": "1.4.1",
"scripts": {
"ng": "ng",
"start": "ng serve",
@@ -11,7 +11,7 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^19.0.0",
"@angular/animations": "^19.0.1",
"@angular/cdk": "^19.0.0",
"@angular/common": "^19.0.0",
"@angular/compiler": "^19.0.0",

BIN
public/rtl-united-text.zip Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,11 +1,13 @@
import { Routes } from '@angular/router';
import {GameComponent} from './game/game.component';
import {WelcomeComponent} from './welcome/welcome.component';
import {FinalComponent} from './final/final.component';
import {CurrentScoreComponent} from './current-score/current-score.component';
import {GameMenuComponent} from './game-menu/game-menu.component';
export const routes: Routes = [
{ path: '', component: WelcomeComponent },
{ path: 'start', component: GameComponent },
{ path: 'start', component: GameMenuComponent },
{ path: 'final', component: FinalComponent },
{ path: 'currentScore', component: CurrentScoreComponent },
];

View File

@@ -0,0 +1,31 @@
/* Algemene stijl voor de game-container */
.game-container {
display: flex;
flex-direction: column;
justify-content: center; /* Verticaal centreren */
align-items: center; /* Horizontaal centreren */
height: 100vh; /* Volledige hoogte van het scherm */
padding: 20px;
max-width: 600px; /* Maximaliseer de breedte van de container */
margin: 0 auto;
}
button{
padding: 10px;
font-size: 1.2rem;
background-color: #ff561e;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 24px;
}
a{
color: white;
text-decoration: none;
}
h2{
font-weight: bold;
}

View File

@@ -0,0 +1,6 @@
<div class="game-container ">
<h2>Ronde {{round}}</h2>
<h4>Tussenstand: {{localStorage.getItem('score')}}/{{round}}0</h4>
<button><a href="#/start">Volgende ronde</a></button>
</div>

View File

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

View File

@@ -0,0 +1,17 @@
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'app-current-score',
imports: [],
templateUrl: './current-score.component.html',
styleUrl: './current-score.component.css'
})
export class CurrentScoreComponent implements OnInit{
round: string;
ngOnInit(): void {
this.round = localStorage.getItem('question')[0]
}
protected readonly localStorage = localStorage;
}

View File

@@ -4,7 +4,7 @@
<h2 (click)="easterEgg()">Je cijfer is: {{ calculatedScore }}</h2>
<h4>{{scoreMessage}}</h4>
<br>
<h4>Aantal vragen goed: {{localStorage.getItem('score')}}/50</h4>
<h5>Aantal vragen goed: {{localStorage.getItem('score')}}/50</h5>
</div>
<a href="#" (click)="resetGame()"><button>Spel opnieuw spelen</button></a>

View File

@@ -0,0 +1,79 @@
.tabs {
position: fixed;
bottom: 0;
display: flex;
left: 50%;
transform: translateX(-50%);
background-color: #fff;
box-shadow: 0 0 1px 0 rgba(24, 94, 224, 0.15), 0 6px 12px 0 rgba(24, 94, 224, 0.15);
padding: 0.75rem;
border-radius: 99px;
margin-bottom: 24px;
}
.tabs * {
z-index: 2;
}
.container input[type="radio"] {
display: none;
}
.tab {
display: flex;
align-items: center;
justify-content: center;
height: 30px;
width: 150px;
font-size: .8rem;
color: black;
font-weight: bold;
border-radius: 99px;
cursor: pointer;
transition: color 0.15s ease-in;
}
.notification {
display: flex;
align-items: center;
justify-content: center;
width: .8rem;
height: .8rem;
position: absolute;
top: 10px;
left: 30%;
border-radius: 50%;
background-color: #e6eef9;
transition: 0.15s ease-in;
}
.container input[type="radio"]:checked + label {
color: #ff561e;
}
.container input[type="radio"]:checked + label > .notification {
background-color: #ff561e;
color: #fff;
margin: 0
}
.container input[id="radio-1"]:checked ~ .glider {
transform: translateX(0);
}
.container input[id="radio-2"]:checked ~ .glider {
transform: translateX(100%);
}
.glider {
position: absolute;
display: flex;
height: 30px;
width: 150px;
background-color: #e6eef9;
opacity: 30%;
z-index: 1;
border-radius: 99px;
transition: 0.25s ease-out;
}

View File

@@ -0,0 +1,16 @@
<app-menu></app-menu>
<div class="container">
<div *ngIf="tab == 1">
<app-game></app-game>
</div>
<div *ngIf="tab == 2">
<app-settings></app-settings>
</div>
<div class="tabs">
<input type="radio" id="radio-1" name="tabs" checked="" (click)="setTab(1)">
<label class="tab" for="radio-1">Spel</label>
<input type="radio" id="radio-2" name="tabs" (click)="setTab(2)">
<label class="tab" for="radio-2">Instellingen</label>
<span class="glider"></span>
</div>
</div>

View File

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

View File

@@ -0,0 +1,24 @@
import { Component } from '@angular/core';
import {GameComponent} from '../game/game.component';
import {NgIf} from '@angular/common';
import {SettingsComponent} from '../settings/settings.component';
import {MenuComponent} from '../menu/menu.component';
@Component({
selector: 'app-game-menu',
imports: [
GameComponent,
NgIf,
SettingsComponent,
MenuComponent
],
templateUrl: './game-menu.component.html',
styleUrl: './game-menu.component.css'
})
export class GameMenuComponent {
tab = 1
setTab(number: number) {
this.tab = number
}
}

View File

@@ -75,7 +75,6 @@
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 50px;
}
.left-column, .right-column {
@@ -92,6 +91,7 @@
border-radius: 5px;
cursor: grab;
text-align: center;
font-weight: bold;
width: 100%;
margin: 5px;
color: white;
@@ -99,11 +99,12 @@
.draggable-button:active {
cursor: grabbing;
background-color: #eb4f1b;
}
.draggable-button.dragging {
background-color: #c0e4ff;
background-color: #eb4f1b;
}
a{

View File

@@ -1,160 +1,156 @@
<app-menu></app-menu>
<div>
</div>
<div class="game-container" *ngIf="currentQuestion.type == 0 && !confirmed">
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div class="question-type">
<p>Kies de soort vraag:</p>
</div>
<div class="buttons">
<button (click)="setQuestionType(1)">Meerkeuze</button>
<button (click)="setQuestionType(2)">Volgorde</button>
<button (click)="setQuestionType(3)">Waar / Niet Waar</button>
</div>
</div>
<div class="game-container" *ngIf="currentQuestion.type == 1 && !confirmed">
<div class="backButton">
<a (click)="currentQuestion.type = 0">← Vorige</a>
</div>
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div class="question-type">
<p>Kies het antwoord: </p>
</div>
<div class="buttons-questions">
<button *ngFor="let item of multipleChoices"
[class.selected]="item.selected"
(click)="toggleChoice(item.choice)">
{{ item.choice }}
</button>
</div>
<div class="buttons-confirm">
<button (click)="confirmAnswer()" [disabled]="answer.length === 0">Bevestigen</button>
</div>
</div>
<div class="game-container" *ngIf="currentQuestion.type == 2 && !confirmed">
<div class="backButton">
<a (click)="currentQuestion.type = 0">← Vorige</a>
</div>
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div class="drag-and-drop-container">
<div id="left" class="left-column" cdkDropList (cdkDropListDropped)="onDrop($event)">
<div *ngFor="let item of leftButtons; let i = index"
cdkDrag
[cdkDragData]="item"
class="draggable-button">
{{ item.label }}
</div>
<div class="game-container" *ngIf="currentQuestion.type == 0 && !confirmed">
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div id="right" class="right-column" cdkDropList (cdkDropListDropped)="onDrop($event)">
<div *ngFor="let item of rightButtons; let i = index"
cdkDrag
[cdkDragData]="item"
class="draggable-button">
{{ item.label }}
</div>
</div>
</div>
<div class="buttons-confirm">
<button (click)="confirmAnswer()">Bevestigen</button>
</div>
</div>
<div class="game-container" *ngIf="currentQuestion.type == 3 && !confirmed">
<div class="backButton">
<a (click)="currentQuestion.type = 0">← Vorige</a>
</div>
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div class="question-type">
<p>Kies het antwoord: </p>
</div>
<div class="buttons-questions">
<button *ngFor="let item of trueFalseChoices"
[class.selected]="item.selected"
(click)="toggleChoiceTrueOrFalse(item.choice)">
{{ item.choice }}
</button>
</div>
<div class="buttons-confirm">
<button (click)="confirmAnswer()" [disabled]="answer.length === 0">Bevestigen</button>
</div>
</div>
<div class="game-container" *ngIf="(currentQuestion.type == 1 || currentQuestion.type == 3) && confirmed">
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div>
<p>Gekozen antwoord: {{ answer.toString() }} </p>
</div>
<div class="question-type">
<p>Klopt het antwoord?</p>
</div>
<div class="buttons-questions">
<button (click)="isAnswerCorrect(true)">Ja</button>
<button (click)="isAnswerCorrect(false)">Nee</button>
</div>
</div>
<div class="game-container" *ngIf="currentQuestion.type == 2 && confirmed">
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div>
<p>Gekozen antwoord:</p>
</div>
<div class="drag-and-drop-container">
<div id="leftConfirmed" class="left-column" cdkDropList (cdkDropListDropped)="onDrop($event)">
<div *ngFor="let item of leftButtons; let i = index"
cdkDrag
[cdkDragData]="item"
class="draggable-button">
{{ item.label }}
</div>
<div class="question-type">
<p>Kies de soort vraag:</p>
</div>
<div id="rightConfirmed" class="right-column" cdkDropList (cdkDropListDropped)="onDrop($event)">
<div *ngFor="let item of rightButtons; let i = index"
cdkDrag
[cdkDragData]="item"
class="draggable-button">
{{ item.label }}
</div>
<div class="buttons">
<button (click)="setQuestionType(1)">Meerkeuze</button>
<button (click)="setQuestionType(2)">Volgorde</button>
<button (click)="setQuestionType(3)">Waar / Niet Waar</button>
</div>
</div>
<div class="question-type">
<p>Klopt het antwoord?</p>
<div class="game-container" *ngIf="currentQuestion.type == 1 && !confirmed">
<div class="backButton">
<a (click)="currentQuestion.type = 0">← Vorige</a>
</div>
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div class="question-type">
<p>Kies het antwoord: </p>
</div>
<div class="buttons-questions">
<button *ngFor="let item of multipleChoices"
[class.selected]="item.selected"
(click)="toggleChoice(item.choice)">
{{ item.choice }}
</button>
</div>
<div class="buttons-confirm">
<button (click)="confirmAnswer()" [disabled]="answer.length === 0">Bevestigen</button>
</div>
</div>
<div class="buttons-questions">
<button (click)="isAnswerCorrect(true)">Ja</button>
<button (click)="isAnswerCorrect(false)">Nee</button>
<div class="game-container" *ngIf="currentQuestion.type == 2 && !confirmed">
<div class="backButton">
<a (click)="currentQuestion.type = 0">← Vorige</a>
</div>
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div class="drag-and-drop-container">
<div id="left" class="left-column" cdkDropList (cdkDropListDropped)="onDrop($event)">
<div *ngFor="let item of leftButtons; let i = index"
cdkDrag
[cdkDragData]="item"
class="draggable-button">
{{ item.label }}
</div>
</div>
<div id="right" class="right-column" cdkDropList (cdkDropListDropped)="onDrop($event)">
<div *ngFor="let item of rightButtons; let i = index"
cdkDrag
[cdkDragData]="item"
class="draggable-button">
{{ item.label }}
</div>
</div>
</div>
<div class="buttons-confirm">
<button (click)="confirmAnswer()">Bevestigen</button>
</div>
</div>
<div class="game-container" *ngIf="currentQuestion.type == 3 && !confirmed">
<div class="backButton">
<a (click)="currentQuestion.type = 0">← Vorige</a>
</div>
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div class="question-type">
<p>Kies het antwoord: </p>
</div>
<div class="buttons-questions">
<button *ngFor="let item of trueFalseChoices"
[class.selected]="item.selected"
(click)="toggleChoiceTrueOrFalse(item.choice)">
{{ item.choice }}
</button>
</div>
<div class="buttons-confirm">
<button (click)="confirmAnswer()" [disabled]="answer.length === 0">Bevestigen</button>
</div>
</div>
<div class="game-container" *ngIf="(currentQuestion.type == 1 || currentQuestion.type == 3) && confirmed">
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div>
<p>Gekozen antwoord: {{ answer.toString() }} </p>
</div>
<div class="question-type">
<p>Klopt het antwoord?</p>
</div>
<div class="buttons-questions">
<button (click)="isAnswerCorrect(true)">Ja</button>
<button (click)="isAnswerCorrect(false)">Nee</button>
</div>
</div>
<div class="game-container" *ngIf="currentQuestion.type == 2 && confirmed">
<div class="question">
<p>Vraag {{ localStorage.getItem('question') }}</p>
</div>
<div>
<p>Gekozen antwoord:</p>
</div>
<div class="drag-and-drop-container">
<div id="leftConfirmed" class="left-column" cdkDropList (cdkDropListDropped)="onDrop($event)">
<div *ngFor="let item of leftButtons; let i = index"
cdkDrag
[cdkDragData]="item"
class="draggable-button">
{{ item.label }}
</div>
</div>
<div id="rightConfirmed" class="right-column" cdkDropList (cdkDropListDropped)="onDrop($event)">
<div *ngFor="let item of rightButtons; let i = index"
cdkDrag
[cdkDragData]="item"
class="draggable-button">
{{ item.label }}
</div>
</div>
</div>
<div class="question-type">
<p>Klopt het antwoord?</p>
</div>
<div class="buttons-questions">
<button (click)="isAnswerCorrect(true)">Ja</button>
<button (click)="isAnswerCorrect(false)">Nee</button>
</div>
</div>
</div>

View File

@@ -1,5 +1,4 @@
import {Component, OnInit} from '@angular/core';
import {MenuComponent} from '../menu/menu.component';
import {CommonModule, NgIf} from '@angular/common';
import {CdkDrag, CdkDragDrop, CdkDropList} from '@angular/cdk/drag-drop';
import {Router} from '@angular/router';
@@ -8,11 +7,10 @@ import {Router} from '@angular/router';
@Component({
selector: 'app-game',
imports: [
MenuComponent,
NgIf,
CdkDrag,
CdkDropList,
CommonModule
CommonModule,
],
templateUrl: './game.component.html',
styleUrl: './game.component.css'
@@ -95,6 +93,9 @@ export class GameComponent implements OnInit {
let question = +localStorage.getItem('question')
if (question < 50){
if (question % 10 == 0){
this.router.navigate(['currentScore'])
}
this.confirmed = false
this.setNewQuestion()
this.resetAnswer()

View File

@@ -0,0 +1,153 @@
.buttons {
display: flex;
flex-direction: column;
gap: 10px;
margin-top: 24px;
}
.buttons button {
padding: 10px;
font-size: 1.2rem;
background-color: white;
color: #ff561e;
border: none;
border-radius: 5px;
cursor: pointer;
box-shadow: 0 0 1px 0 rgba(24, 94, 224, 0.15), 0 6px 12px 0 rgba(24, 94, 224, 0.15);
margin-top: 8px;
}
.card {
width: 300px;
height: fit-content;
background: rgb(255, 255, 255);
border-radius: 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 20px;
padding: 30px;
position: relative;
box-shadow: 20px 20px 30px rgba(0, 0, 0, 0.068);
}
.card-content {
width: 100%;
height: fit-content;
display: flex;
flex-direction: column;
gap: 5px;
}
.card-heading {
font-size: 20px;
font-weight: 700;
color: rgb(27, 27, 27);
}
.card-description {
font-weight: 100;
color: rgb(102, 102, 102);
}
.card-button-wrapper {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
}
.card-button {
width: 50%;
height: 35px;
border-radius: 10px;
border: none;
cursor: pointer;
font-weight: 600;
}
.primary {
background-color: #ff561e;
color: white;
}
.primary:hover {
background-color: rgb(255, 73, 66);
}
.secondary {
background-color: #ddd;
}
.secondary:hover {
background-color: rgb(197, 197, 197);
}
.exit-button {
display: flex;
align-items: center;
justify-content: center;
border: none;
background-color: transparent;
position: absolute;
top: 20px;
right: 20px;
cursor: pointer;
}
.exit-button:hover svg {
fill: black;
}
.exit-button svg {
fill: rgb(175, 175, 175);
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.input-container {
position: relative;
margin: 50px auto;
width: auto;
}
.input-container input[type="text"] {
font-size: 20px;
width: 100%;
border: none;
border-bottom: 2px solid #ccc;
padding: 5px 0;
background-color: transparent;
outline: none;
}
.input-container .label {
position: absolute;
top: 0;
left: 0;
color: #ccc;
transition: all 0.3s ease;
pointer-events: none;
}
.input-container input[type="text"]:focus ~ .label,
.input-container input[type="text"]:valid ~ .label {
top: -20px;
font-size: 16px;
color: #333;
}
.input-container .underline {
position: absolute;
bottom: 0;
left: 0;
height: 2px;
width: 100%;
background-color: #333;
transform: scaleX(0);
transition: all 0.3s ease;
}
.input-container input[type="text"]:focus ~ .underline,
.input-container input[type="text"]:valid ~ .underline {
transform: scaleX(1);
}

View File

@@ -0,0 +1,52 @@
<div class="container">
<h3>Instellingen</h3>
<div class="buttons">
<button (click)="openModalChange()">Naam aanpassen</button>
<button (click)="openModal()">Spel afsluiten</button>
</div>
</div>
<div *ngIf="showModalClose" class="modal-overlay" (click)="closeModalClose()">
<div class="card" (click)="$event.stopPropagation()">
<div class="card-content">
<p class="card-heading">Spel afsluiten</p>
<p class="card-description">Weet je het zeker? Je zal je score kwijt raken.</p>
</div>
<div class="card-button-wrapper">
<button class="card-button secondary" (click)="closeModalClose()">Annuleren</button>
<button class="card-button primary" (click)="closeGame()">Afsluiten</button>
</div>
<button class="exit-button" (click)="closeModalClose()">
<svg height="20px" viewBox="0 0 384 512">
<path
d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"
></path>
</svg>
</button>
</div>
</div>
<div *ngIf="showModalChange" class="modal-overlay" (click)="closeModalChange()">
<div class="card" (click)="$event.stopPropagation()" [formGroup]="nameForm">
<div class="card-content">
<p class="card-heading">Naam aanpassen</p>
<div class="input-container">
<input type="text" id="naam" formControlName="naam" required="">
<label for="naam" class="label">Naam</label>
<div class="underline"></div>
</div>
</div>
<div class="card-button-wrapper">
<button class="card-button secondary" (click)="closeModalChange()">Annuleren</button>
<button class="card-button primary" (click)="changeName()">Aanpassen</button>
</div>
<button class="exit-button" (click)="closeModalChange()">
<svg height="20px" viewBox="0 0 384 512">
<path
d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"
></path>
</svg>
</button>
</div>
</div>

View File

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

View File

@@ -0,0 +1,56 @@
import {Component, OnInit} from '@angular/core';
import {NgIf} from '@angular/common';
import {Router} from '@angular/router';
import {FormControl, FormGroup, FormsModule, ReactiveFormsModule} from '@angular/forms';
@Component({
selector: 'app-settings',
imports: [
NgIf,
FormsModule,
ReactiveFormsModule
],
templateUrl: './settings.component.html',
styleUrl: './settings.component.css'
})
export class SettingsComponent implements OnInit{
constructor(private router: Router) {
}
showModalClose: boolean = false;
showModalChange: boolean = false;
nameForm: FormGroup
ngOnInit(): void {
this.nameForm = new FormGroup({
naam: new FormControl(localStorage.getItem('name'))
})
}
openModal() {
this.showModalClose = true;
}
closeModalClose() {
this.showModalClose = false;
}
closeGame() {
this.router.navigate([''])
localStorage.clear()
}
openModalChange() {
this.showModalChange = true;
}
closeModalChange() {
this.showModalChange = false;
}
changeName() {
localStorage.setItem('name', this.nameForm.get('naam').value)
this.closeModalChange()
}
}

View File

@@ -25,6 +25,7 @@ body, html {
.form {
text-align: right;
margin-top: 12px;
}
.form p {
@@ -53,10 +54,64 @@ button {
cursor: pointer;
}
button[disabled] {
background-color: #cccccc;
color: #666666;
}
a{
color: #ff561e;
}
.input-container {
position: relative;
margin: 50px auto;
width: 300px;
}
.input-container input[type="text"] {
font-size: 20px;
width: 100%;
border: none;
border-bottom: 2px solid #ccc;
padding: 5px 0;
background-color: transparent;
outline: none;
}
.input-container .label {
position: absolute;
top: 0;
left: 0;
color: #ccc;
transition: all 0.3s ease;
pointer-events: none;
}
.input-container input[type="text"]:focus ~ .label,
.input-container input[type="text"]:valid ~ .label {
top: -20px;
font-size: 16px;
color: #333;
}
.input-container .underline {
position: absolute;
bottom: 0;
left: 0;
height: 2px;
width: 100%;
background-color: #333;
transform: scaleX(0);
transition: all 0.3s ease;
}
.input-container input[type="text"]:focus ~ .underline,
.input-container input[type="text"]:valid ~ .underline {
transform: scaleX(1);
}
@media (max-width: 600px) {
.container {

View File

@@ -2,10 +2,15 @@
<div class="logo">
<img src="Logo.png" alt="Logo">
</div>
<h2>Weet ik Veel</h2>
<div class="form" [formGroup]="form">
<p>Voer hier je naam in om te beginnen</p>
<input type="text" placeholder="Naam" formControlName="naam">
<button (click)="start()">Beginnen</button>
<div class="input-container">
<input type="text" id="naam" formControlName="naam" required="">
<label for="naam" class="label">Naam</label>
<div class="underline"></div>
</div>
<button (click)="start()" [disabled]="form.get('naam').value == '' ">Beginnen</button>
</div>
<div *ngIf="localStorage.getItem('name') != undefined">

View File

@@ -4,3 +4,87 @@ html, body {
padding: 0;
height: 100%; /* Voor volledige pagina-centrering */
}
/* Definieer RTLUnitedTextBold */
@font-face {
font-family: 'RTLUnitedText';
src: url('../public/rtl-united-text/RTLUnitedTextBold.ttf') format('truetype');
font-weight: bold;
font-style: normal;
}
/* Definieer RTLUnitedTextBoldItalic */
@font-face {
font-family: 'RTLUnitedText';
src: url('../public/rtl-united-text/RTLUnitedTextBoldItalic.ttf') format('truetype');
font-weight: bold;
font-style: italic;
}
/* Definieer RTLUnitedTextLight */
@font-face {
font-family: 'RTLUnitedText';
src: url('../public/rtl-united-text/RTLUnitedTextLight.ttf') format('truetype');
font-weight: 300; /* Licht gewicht */
font-style: normal;
}
/* Definieer RTLUnitedTextLightItalic */
@font-face {
font-family: 'RTLUnitedText';
src: url('../public/rtl-united-text/RTLUnitedTextLightItalic.ttf') format('truetype');
font-weight: 300; /* Licht gewicht */
font-style: italic;
}
/* Definieer RTLUnitedTextRegular */
@font-face {
font-family: 'RTLUnitedText';
src: url('../public/rtl-united-text/RTLUnitedTextRegular.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
/* Definieer RTLUnitedTextRegularItalic */
@font-face {
font-family: 'RTLUnitedText';
src: url('../public/rtl-united-text/RTLUnitedTextRegularItalic.ttf') format('truetype');
font-weight: normal;
font-style: italic;
}
/* Voorbeeld van gebruik */
body {
font-family: 'RTLUnitedText', sans-serif;
}
h1, h2, h3, h4{
font-weight: bold;
}
.container-background {
width: 100%;
height: 100%;
/* Add your background pattern here */
background-color: #ffffff;
background-image: radial-gradient(rgba(12, 12, 12, 0.171) 2px, transparent 0);
background-size: 30px 30px;
background-position: -5px -5px;
}
button{
font-weight: bold;
}
button:active{
background-color: #eb4f1b;
}
.container {
display: flex;
flex-direction: column;
justify-content: center; /* Verticaal centreren */
align-items: center; /* Horizontaal centreren */
height: 100vh; /* Volledige hoogte van het scherm */
padding: 20px;
max-width: 600px; /* Maximaliseer de breedte van de container */
margin: 0 auto;
}