Compare commits
9 Commits
icon
...
5a20e76df2
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a20e76df2 | |||
|
|
02c5c6ea68 | ||
|
|
9cbb8756d1 | ||
|
|
604b92b3b3 | ||
|
|
c7236394d9 | ||
|
|
720ef83c2e | ||
|
|
5b1d107cac | ||
|
|
662257ebc5 | ||
|
|
ad48882bca |
1
backend/.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
*.db3
|
*.db3
|
||||||
*.db3-*
|
*.db3-*
|
||||||
|
*.db3.*
|
||||||
/allowance_planner
|
/allowance_planner
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ type ServerConfig struct {
|
|||||||
Started chan bool
|
Started chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DefaultDomain = "localhost:8080"
|
||||||
|
|
||||||
|
// The domain that the server is reachable at.
|
||||||
|
var domain = DefaultDomain
|
||||||
|
|
||||||
func getUsers(c *gin.Context) {
|
func getUsers(c *gin.Context) {
|
||||||
users, err := db.GetUsers()
|
users, err := db.GetUsers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -706,5 +711,10 @@ func main() {
|
|||||||
config.Datasource = "allowance_planner.db3"
|
config.Datasource = "allowance_planner.db3"
|
||||||
log.Printf("Warning: No DB_PATH set, using default of %s", config.Datasource)
|
log.Printf("Warning: No DB_PATH set, using default of %s", config.Datasource)
|
||||||
}
|
}
|
||||||
|
domain = os.Getenv("DOMAIN")
|
||||||
|
if domain == "" {
|
||||||
|
domain = DefaultDomain
|
||||||
|
log.Printf("Warning: No DOMAIN set, using default of %s", domain)
|
||||||
|
}
|
||||||
start(context.Background(), &config)
|
start(context.Background(), &config)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
@@ -26,11 +27,22 @@ func loadWebEndpoints(router *gin.Engine) {
|
|||||||
router.GET("/completeAllowance", renderCompleteAllowance)
|
router.GET("/completeAllowance", renderCompleteAllowance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func redirectToPage(c *gin.Context, page string) {
|
||||||
|
redirectToPageStatus(c, page, http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
func redirectToPageStatus(c *gin.Context, page string, status int) {
|
||||||
|
scheme := c.Request.URL.Scheme
|
||||||
|
target := scheme + domain + page
|
||||||
|
c.Redirect(status, target)
|
||||||
|
}
|
||||||
|
|
||||||
func renderLogin(c *gin.Context) {
|
func renderLogin(c *gin.Context) {
|
||||||
if c.Query("user") != "" {
|
if c.Query("user") != "" {
|
||||||
c.SetCookie("user", c.Query("user"), 3600, "/", "localhost", false, true)
|
log.Println("Set cookie for user:", c.Query("user"))
|
||||||
|
c.SetCookie("user", c.Query("user"), 3600, "", "", false, true)
|
||||||
}
|
}
|
||||||
c.Redirect(http.StatusFound, "/")
|
redirectToPage(c, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderIndex(c *gin.Context) {
|
func renderIndex(c *gin.Context) {
|
||||||
@@ -68,7 +80,7 @@ func renderCreateTask(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Redirect(http.StatusFound, "/")
|
redirectToPageStatus(c, "/", http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderCompleteTask(c *gin.Context) {
|
func renderCompleteTask(c *gin.Context) {
|
||||||
@@ -85,7 +97,7 @@ func renderCompleteTask(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Redirect(http.StatusFound, "/")
|
redirectToPageStatus(c, "/", http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderCreateAllowance(c *gin.Context) {
|
func renderCreateAllowance(c *gin.Context) {
|
||||||
@@ -122,7 +134,7 @@ func renderCreateAllowance(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Redirect(http.StatusFound, "/")
|
redirectToPageStatus(c, "/", http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderCompleteAllowance(c *gin.Context) {
|
func renderCompleteAllowance(c *gin.Context) {
|
||||||
@@ -144,11 +156,12 @@ func renderCompleteAllowance(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Redirect(http.StatusFound, "/")
|
redirectToPageStatus(c, "/", http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCurrentUser(c *gin.Context) *int {
|
func getCurrentUser(c *gin.Context) *int {
|
||||||
currentUserStr, err := c.Cookie("user")
|
currentUserStr, err := c.Cookie("user")
|
||||||
|
log.Println("Cookie string:", currentUserStr)
|
||||||
if errors.Is(err, http.ErrNoCookie) {
|
if errors.Is(err, http.ErrNoCookie) {
|
||||||
renderNoUser(c)
|
renderNoUser(c)
|
||||||
return nil
|
return nil
|
||||||
@@ -172,7 +185,7 @@ func getCurrentUser(c *gin.Context) *int {
|
|||||||
|
|
||||||
func unsetUserCookie(c *gin.Context) {
|
func unsetUserCookie(c *gin.Context) {
|
||||||
c.SetCookie("user", "", -1, "/", "localhost", false, true)
|
c.SetCookie("user", "", -1, "/", "localhost", false, true)
|
||||||
c.Redirect(http.StatusFound, "/")
|
redirectToPageStatus(c, "/", http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderNoUser(c *gin.Context) {
|
func renderNoUser(c *gin.Context) {
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Allowance Planner 2000</title>
|
<title>Allowance Planner 2000</title>
|
||||||
<style>
|
<style>
|
||||||
|
<!--
|
||||||
tr:hover {
|
tr:hover {
|
||||||
background-color: #f0f0f0;
|
background-color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
-->
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -27,7 +29,7 @@
|
|||||||
{{if ne .CurrentUser 0}}
|
{{if ne .CurrentUser 0}}
|
||||||
<h2>Allowances</h2>
|
<h2>Allowances</h2>
|
||||||
<form action="/createAllowance" method="post">
|
<form action="/createAllowance" method="post">
|
||||||
<table border="1">
|
<table border=1>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
@@ -43,7 +45,7 @@
|
|||||||
<td></td>
|
<td></td>
|
||||||
<td><label><input type="number" name="target" placeholder="Target"></label></td>
|
<td><label><input type="number" name="target" placeholder="Target"></label></td>
|
||||||
<td><label><input type="number" name="weight" placeholder="Weight"></label></td>
|
<td><label><input type="number" name="weight" placeholder="Weight"></label></td>
|
||||||
<td><button>Create</button></td>
|
<td><input type="submit" value="Create"></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{range .Allowances}}
|
{{range .Allowances}}
|
||||||
{{if eq .ID 0}}
|
{{if eq .ID 0}}
|
||||||
@@ -103,7 +105,7 @@
|
|||||||
<td><label><input type="text" name="name" placeholder="Name"></label></td>
|
<td><label><input type="text" name="name" placeholder="Name"></label></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><label><input type="number" name="reward" placeholder="Reward"></label></td>
|
<td><label><input type="number" name="reward" placeholder="Reward"></label></td>
|
||||||
<td><button>Create</button></td>
|
<td><input type="submit" value="Create"></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 16 KiB |
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background>
|
||||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
<inset android:drawable="@mipmap/ic_launcher_background" android:inset="16.7%" />
|
||||||
|
</background>
|
||||||
|
<foreground>
|
||||||
|
<inset android:drawable="@mipmap/ic_launcher_foreground" android:inset="16.7%" />
|
||||||
|
</foreground>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background>
|
||||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
<inset android:drawable="@mipmap/ic_launcher_background" android:inset="16.7%" />
|
||||||
|
</background>
|
||||||
|
<foreground>
|
||||||
|
<inset android:drawable="@mipmap/ic_launcher_foreground" android:inset="16.7%" />
|
||||||
|
</foreground>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
|
After Width: | Height: | Size: 660 B |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 296 B |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 408 B |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 1006 B |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 18 KiB |
@@ -1,7 +1,7 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">allowance-planner-v2</string>
|
<string name="app_name">Allowance Planner V2</string>
|
||||||
<string name="title_activity_main">allowance-planner-v2</string>
|
<string name="title_activity_main">Allowance Planner V2</string>
|
||||||
<string name="package_name">io.ionic.starter</string>
|
<string name="package_name">io.ionic.starter</string>
|
||||||
<string name="custom_url_scheme">io.ionic.starter</string>
|
<string name="custom_url_scheme">io.ionic.starter</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
BIN
frontend/allowance-planner-v2/assets/icon-background.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
frontend/allowance-planner-v2/assets/icon-foreground.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
BIN
frontend/allowance-planner-v2/assets/splash.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
@@ -2,7 +2,7 @@ import type { CapacitorConfig } from '@capacitor/cli';
|
|||||||
|
|
||||||
const config: CapacitorConfig = {
|
const config: CapacitorConfig = {
|
||||||
appId: 'io.ionic.starter',
|
appId: 'io.ionic.starter',
|
||||||
appName: 'allowance-planner-v2',
|
appName: 'Allowance Planner V2',
|
||||||
webDir: 'www'
|
webDir: 'www'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
3471
frontend/allowance-planner-v2/package-lock.json
generated
@@ -47,6 +47,7 @@
|
|||||||
"@angular/cli": "^19.0.0",
|
"@angular/cli": "^19.0.0",
|
||||||
"@angular/compiler-cli": "^19.0.0",
|
"@angular/compiler-cli": "^19.0.0",
|
||||||
"@angular/language-service": "^19.0.0",
|
"@angular/language-service": "^19.0.0",
|
||||||
|
"@capacitor/assets": "^3.0.5",
|
||||||
"@capacitor/cli": "7.2.0",
|
"@capacitor/cli": "7.2.0",
|
||||||
"@ionic/angular-toolkit": "^12.0.0",
|
"@ionic/angular-toolkit": "^12.0.0",
|
||||||
"@types/jasmine": "~5.1.0",
|
"@types/jasmine": "~5.1.0",
|
||||||
|
|||||||
@@ -18,6 +18,16 @@ form,
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
border: 1px solid var(--ion-color-primary);
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 250px;
|
||||||
|
height: 40px;
|
||||||
|
padding-inline: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
color: var(--ion-color-primary);
|
color: var(--ion-color-primary);
|
||||||
margin-top: 25px;
|
margin-top: 25px;
|
||||||
@@ -30,8 +40,7 @@ button {
|
|||||||
color: white;
|
color: white;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
margin-top: auto;
|
margin-top: 100px;
|
||||||
margin-bottom: 50px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button:disabled,
|
button:disabled,
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export class AllowancePage implements ViewWillEnter {
|
|||||||
allowance[0].name = 'Main Allowance';
|
allowance[0].name = 'Main Allowance';
|
||||||
this.allowance$.next(allowance);
|
this.allowance$.next(allowance);
|
||||||
})
|
})
|
||||||
}, 50);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
canFinishGoal(allowance: Allowance): boolean {
|
canFinishGoal(allowance: Allowance): boolean {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { EditAllowancePageRoutingModule } from './edit-allowance-routing.module'
|
|||||||
|
|
||||||
import { EditAllowancePage } from './edit-allowance.page';
|
import { EditAllowancePage } from './edit-allowance.page';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -16,7 +17,8 @@ import { MatIconModule } from '@angular/material/icon';
|
|||||||
IonicModule,
|
IonicModule,
|
||||||
EditAllowancePageRoutingModule,
|
EditAllowancePageRoutingModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatIconModule
|
MatIconModule,
|
||||||
|
MatSelectModule
|
||||||
],
|
],
|
||||||
declarations: [EditAllowancePage]
|
declarations: [EditAllowancePage]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,11 +7,6 @@
|
|||||||
<ion-title *ngIf="isAddMode">Create Goal</ion-title>
|
<ion-title *ngIf="isAddMode">Create Goal</ion-title>
|
||||||
<ion-title *ngIf="!isAddMode && goalId != 0">Edit Goal</ion-title>
|
<ion-title *ngIf="!isAddMode && goalId != 0">Edit Goal</ion-title>
|
||||||
<ion-title *ngIf="!isAddMode && goalId == 0">Edit Allowance</ion-title>
|
<ion-title *ngIf="!isAddMode && goalId == 0">Edit Allowance</ion-title>
|
||||||
<button
|
|
||||||
*ngIf="!isAddMode && goalId !=0"
|
|
||||||
class="remove-button"
|
|
||||||
(click)="deleteAllowance()"
|
|
||||||
>Delete Goal</button>
|
|
||||||
</div>
|
</div>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
@@ -33,9 +28,9 @@
|
|||||||
|
|
||||||
<div class="item" *ngIf="isAddMode || goalId != 0">
|
<div class="item" *ngIf="isAddMode || goalId != 0">
|
||||||
<label>Colour</label>
|
<label>Colour</label>
|
||||||
<select formControlName="color">
|
<mat-select [(value)]="selectedColor" formControlName="color" [style.--color]="selectedColor">
|
||||||
<option *ngFor="let color of possibleColors" [value]="color" [style.--background]="color">{{color}}</option>
|
<mat-option *ngFor="let color of possibleColors" [value]="color" [style.--background]="color">{{color}}</mat-option>
|
||||||
</select>
|
</mat-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="button" [disabled]="!form.valid" (click)="submit()">
|
<button type="button" [disabled]="!form.valid" (click)="submit()">
|
||||||
@@ -43,5 +38,10 @@
|
|||||||
<span *ngIf="!isAddMode && goalId != 0">Update Goal</span>
|
<span *ngIf="!isAddMode && goalId != 0">Update Goal</span>
|
||||||
<span *ngIf="!isAddMode && goalId == 0">Update Allowance</span>
|
<span *ngIf="!isAddMode && goalId == 0">Update Allowance</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="!isAddMode && goalId !=0"
|
||||||
|
class="remove-button"
|
||||||
|
(click)="deleteAllowance()"
|
||||||
|
>Delete Goal</button>
|
||||||
</form>
|
</form>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -4,10 +4,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.remove-button {
|
.remove-button {
|
||||||
background-color: var(--ion-color-primary);
|
margin-top: 10px;
|
||||||
margin-right: 15px;
|
background-color: var(--negative-amount-color);
|
||||||
width: 100px;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
@@ -28,17 +26,23 @@ label {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input,
|
input,
|
||||||
select {
|
mat-select {
|
||||||
|
--color: black;
|
||||||
|
color: var(--color);
|
||||||
border: 1px solid var(--ion-color-primary);
|
border: 1px solid var(--ion-color-primary);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
|
height: 40px;
|
||||||
|
padding-inline: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-family: (--ion-font-family);
|
||||||
}
|
}
|
||||||
|
|
||||||
option {
|
mat-option {
|
||||||
--background: white;
|
--background: white;
|
||||||
background-color: var(--background);
|
|
||||||
color: var(--background);
|
color: var(--background);
|
||||||
font-family: var(--ion-font-family);
|
font-family: (--ion-font-family);
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@@ -47,8 +51,7 @@ button {
|
|||||||
color: white;
|
color: white;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
margin-top: auto;
|
margin-top: 100px;
|
||||||
margin-bottom: 50px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button:disabled,
|
button:disabled,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export class EditAllowancePage implements OnInit {
|
|||||||
public goalId: number;
|
public goalId: number;
|
||||||
public userId: number;
|
public userId: number;
|
||||||
public isAddMode: boolean;
|
public isAddMode: boolean;
|
||||||
|
public selectedColor: string = '';
|
||||||
public possibleColors: Array<string> = [
|
public possibleColors: Array<string> = [
|
||||||
'#6199D9',
|
'#6199D9',
|
||||||
'#D98B61',
|
'#D98B61',
|
||||||
@@ -73,6 +74,7 @@ export class EditAllowancePage implements OnInit {
|
|||||||
weight: allowance.weight,
|
weight: allowance.weight,
|
||||||
color: allowance.colour
|
color: allowance.colour
|
||||||
});
|
});
|
||||||
|
this.selectedColor = this.form.value.color;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { EditTaskPageRoutingModule } from './edit-task-routing.module';
|
|||||||
|
|
||||||
import { EditTaskPage } from './edit-task.page';
|
import { EditTaskPage } from './edit-task.page';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -16,7 +17,8 @@ import { MatIconModule } from '@angular/material/icon';
|
|||||||
IonicModule,
|
IonicModule,
|
||||||
EditTaskPageRoutingModule,
|
EditTaskPageRoutingModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatIconModule
|
MatIconModule,
|
||||||
|
MatSelectModule
|
||||||
],
|
],
|
||||||
declarations: [EditTaskPage]
|
declarations: [EditTaskPage]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,11 +6,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<ion-title *ngIf="isAddMode">Create Task</ion-title>
|
<ion-title *ngIf="isAddMode">Create Task</ion-title>
|
||||||
<ion-title *ngIf="!isAddMode">Edit Task</ion-title>
|
<ion-title *ngIf="!isAddMode">Edit Task</ion-title>
|
||||||
<button
|
|
||||||
*ngIf="!isAddMode"
|
|
||||||
class="remove-button"
|
|
||||||
(click)="deleteTask()"
|
|
||||||
>Delete task</button>
|
|
||||||
</div>
|
</div>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
@@ -24,13 +19,18 @@
|
|||||||
<input id="reward" type="number" placeholder="0.00" name="price" min="0" value="0" step="0.01" formControlName="reward"/>
|
<input id="reward" type="number" placeholder="0.00" name="price" min="0" value="0" step="0.01" formControlName="reward"/>
|
||||||
|
|
||||||
<label>Assigned</label>
|
<label>Assigned</label>
|
||||||
<select formControlName="assigned">
|
<mat-select formControlName="assigned">
|
||||||
<option *ngFor="let user of users" [value]="user.id">{{ user.name }}</option>
|
<mat-option *ngFor="let user of users" [value]="user.id">{{ user.name }}</mat-option>
|
||||||
</select>
|
</mat-select>
|
||||||
|
|
||||||
<button type="button" [disabled]="!form.valid" (click)="submit()">
|
<button type="button" [disabled]="!form.valid" (click)="submit()">
|
||||||
<span *ngIf="isAddMode">Add Task</span>
|
<span *ngIf="isAddMode">Add Task</span>
|
||||||
<span *ngIf="!isAddMode">Update Task</span>
|
<span *ngIf="!isAddMode">Update Task</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="!isAddMode"
|
||||||
|
class="remove-button"
|
||||||
|
(click)="deleteTask()"
|
||||||
|
>Delete task</button>
|
||||||
</form>
|
</form>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|||||||
@@ -4,10 +4,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.remove-button {
|
.remove-button {
|
||||||
background-color: var(--ion-color-primary);
|
margin-top: 10px;
|
||||||
margin-right: 15px;
|
background-color: var(--negative-amount-color);
|
||||||
width: 95px;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
@@ -24,10 +22,15 @@ label {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input,
|
input,
|
||||||
select {
|
mat-select {
|
||||||
border: 1px solid var(--ion-color-primary);
|
border: 1px solid var(--ion-color-primary);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
|
height: 40px;
|
||||||
|
padding-inline: 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-family: (--ion-font-family);
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@@ -36,8 +39,7 @@ button {
|
|||||||
color: white;
|
color: white;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
margin-top: auto;
|
margin-top: 100px;
|
||||||
margin-bottom: 50px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button:disabled,
|
button:disabled,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
.left {
|
.left {
|
||||||
width: 70%;
|
width: 70%;
|
||||||
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.date {
|
.date {
|
||||||
|
|||||||
@@ -18,8 +18,12 @@
|
|||||||
<div class="task" *ngFor="let task of tasks$ | async">
|
<div class="task" *ngFor="let task of tasks$ | async">
|
||||||
<button (click)="completeTask(task.id)">Done</button>
|
<button (click)="completeTask(task.id)">Done</button>
|
||||||
<div (click)="updateTask(task.id)" class="item">
|
<div (click)="updateTask(task.id)" class="item">
|
||||||
<div class="name">{{ task.name }}</div>
|
<div class="text">
|
||||||
<div class="assigned">{{ usernames[task.assigned ? task.assigned : 0] }}</div>
|
<div class="name">
|
||||||
|
{{ task.name }}
|
||||||
|
<span class="assigned">{{ usernames[task.assigned ? task.assigned : 0] }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="reward"
|
class="reward"
|
||||||
[ngClass]="{ 'negative': task.reward < 0 }"
|
[ngClass]="{ 'negative': task.reward < 0 }"
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ mat-icon {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: 1px solid var(--line-color);
|
border-bottom: 1px solid var(--line-color);
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
|
padding-block: 10px;
|
||||||
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
@@ -41,7 +43,6 @@ mat-icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
margin-left: 10px;
|
|
||||||
color: var(--font-color);
|
color: var(--font-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ mat-icon {
|
|||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
color: var(--positive-amount-color);
|
color: var(--positive-amount-color);
|
||||||
|
font-size: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.negative {
|
.negative {
|
||||||
@@ -56,21 +58,28 @@ mat-icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
width: 57px;
|
height: 45px;
|
||||||
height: 30px;
|
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
color: white;
|
color: white;
|
||||||
background: var(--confirm-button-color);
|
background: var(--confirm-button-color);
|
||||||
|
padding-inline: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-button {
|
.add-button {
|
||||||
background-color: var(--ion-color-primary);
|
background-color: var(--ion-color-primary);
|
||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
width: 75px;
|
height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.assigned {
|
.assigned {
|
||||||
color: var(--line-color);
|
color: var(--line-color);
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
font-size: 12px;
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 60%;
|
||||||
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,7 @@ export class TasksPage implements ViewWillEnter {
|
|||||||
this.taskService.getTaskList().subscribe(tasks => {
|
this.taskService.getTaskList().subscribe(tasks => {
|
||||||
this.tasks$.next(tasks);
|
this.tasks$.next(tasks);
|
||||||
});
|
});
|
||||||
}, 50);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
createTask() {
|
createTask() {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
ion-title {
|
ion-title {
|
||||||
color: var(--ion-color-primary);
|
color: var(--ion-color-primary);
|
||||||
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-header {
|
ion-header {
|
||||||
@@ -46,4 +47,25 @@ ion-header {
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-header.md {
|
||||||
|
ion-toolbar:first-child {
|
||||||
|
--padding-top: 30px;
|
||||||
|
--padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-alert .alert-wrapper.sc-ion-alert-md {
|
||||||
|
background-color: var(--ion-background-color) !important;
|
||||||
|
--background: unset !important;
|
||||||
|
box-shadow: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-alert .alert-tappable.sc-ion-alert-md {
|
||||||
|
background-color: var(--test-color);
|
||||||
}
|
}
|
||||||