diff --git a/resources/components/favourites/save.html b/resources/components/favourites/save.html
index 6f31d62..0347554 100644
--- a/resources/components/favourites/save.html
+++ b/resources/components/favourites/save.html
@@ -16,9 +16,19 @@
-
+
+
+
+
+
+
+
diff --git a/resources/styles/_controls.scss b/resources/styles/_controls.scss
index 6a479c8..e8879c4 100644
--- a/resources/styles/_controls.scss
+++ b/resources/styles/_controls.scss
@@ -13,6 +13,12 @@
}
}
+ &.btn-xs {
+ font-size: 0.75rem;
+ font-weight: bold;
+ padding: 0.25rem 0.5rem;
+ }
+
border-radius: 1.5px;
display: inline-block;
@@ -29,4 +35,13 @@
border: 1px $primary solid;
}
}
+
+ &.btn-danger {
+ background: $danger-gradient;
+ border-color: transparent;
+
+ &:hover {
+ border: 1px $danger solid;
+ }
+ }
}
diff --git a/resources/styles/main.scss b/resources/styles/main.scss
index 67dc67a..ada8ede 100644
--- a/resources/styles/main.scss
+++ b/resources/styles/main.scss
@@ -2,12 +2,14 @@ $border-radius: 0;
$border-radius-lg: $border-radius;
$border-radius-sm: $border-radius;
+$danger: #cd2e12;
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
$primary: #005ea8;
$primary-gradient: linear-gradient(120deg, #0083c5 10%, #005ea8 90%);
+$danger-gradient: linear-gradient(120deg, $danger 10%, darken($danger, 10%) 90%);
$custom-control-indicator-checked-bg: $dark;
$custom-control-indicator-active-bg: $dark;
diff --git a/resources/styles/ui/_modal.scss b/resources/styles/ui/_modal.scss
index 770be0b..242138c 100644
--- a/resources/styles/ui/_modal.scss
+++ b/resources/styles/ui/_modal.scss
@@ -73,6 +73,7 @@ $dialog-sizes: (
@each $size, $width in $dialog-sizes {
.ui-modal.ui-modal--#{$size} {
width: 100%;
+ box-sizing: border-box;
}
}
}
diff --git a/resources/ts/components/favourites.ts b/resources/ts/components/favourites.ts
index 5a5f5bf..a7e0fd1 100644
--- a/resources/ts/components/favourites.ts
+++ b/resources/ts/components/favourites.ts
@@ -1,8 +1,7 @@
import Vue from 'vue'
-import { Component, Prop } from 'vue-property-decorator'
-import { namespace, State, Mutation } from "vuex-class";
+import { Component, Watch } from 'vue-property-decorator'
+import { Mutation, State } from "vuex-class";
import { Favourite } from "../store/favourites";
-import { SavedState } from "../store/root";
import { Stop } from "../model";
import * as uuid from "uuid";
import { Favourites } from "../store";
@@ -34,8 +33,15 @@ export class FavouritesAdderComponent extends Vue {
private name = "";
private errors = { name: [] };
+ private confirmation = false;
+
@Favourites.Mutation add: (favourite: Favourite) => void;
+ @Watch('name')
+ handleNameChange() {
+ this.confirmation = false;
+ }
+
async save() {
const favourite: Favourite = createFavouriteEntry(this.name, this.stops);
@@ -54,8 +60,9 @@ export class FavouritesAdderComponent extends Vue {
errors.name.push("Musisz podać nazwę.");
}
- if (this.$store.state.favourites.favourites.filter(other => other.name == favourite.name).length > 0) {
+ if (this.$store.state.favourites.favourites.filter(other => other.name == favourite.name).length > 0 && !this.confirmation) {
errors.name.push("Istnieje już zapisana grupa przystanków o takiej nazwie.");
+ this.confirmation = true;
}
this.errors = errors;
diff --git a/resources/ts/components/ui/icon.ts b/resources/ts/components/ui/icon.ts
index b25535a..2dad8a9 100644
--- a/resources/ts/components/ui/icon.ts
+++ b/resources/ts/components/ui/icon.ts
@@ -53,12 +53,12 @@ const simple = (icon: IconDefinition, props: any = {}): SimpleIcon => ({
icon, ...props, type: "simple"
});
-const stack = (icons: IconDescription[]): StackedIcon => ({type: "stacked", icons});
+const stack = (icons: IconDescription[]): StackedIcon => ({ type: "stacked", icons });
const lineTypeIcons = Object
.values(fac)
- .map<[string, Icon]>(icon => [ `line-${icon.iconName}`, simple(icon) ])
- .reduce((acc, [icon, definition]) => ({ ...acc, [icon]: definition}), {})
+ .map<[string, Icon]>(icon => [`line-${ icon.iconName }`, simple(icon)])
+ .reduce((acc, [icon, definition]) => ({ ...acc, [icon]: definition }), {})
const messageTypeIcons: Dictionary = {
'message-breakdown': simple(faExclamationTriangle),
@@ -66,7 +66,7 @@ const messageTypeIcons: Dictionary = {
'message-unknown': simple(faQuestionCircle),
};
-const definitions: Dictionary = {
+const definitions = {
'favourite': simple(faStar),
'unknown': simple(faQuestionSquare),
'add': simple(faCheck),
@@ -93,14 +93,16 @@ const definitions: Dictionary = {
'decrement': simple(faMinus, { "fixed-width": true }),
'relative-time': simple(faHourglassHalf),
'departure-warning': stack([
- {icon: faClockBold},
- {icon: faSolidExclamationTriangle, transform: "shrink-5 down-4 right-6"}
+ { icon: faClockBold },
+ { icon: faSolidExclamationTriangle, transform: "shrink-5 down-4 right-6" }
]),
'close': simple(faTimes),
...lineTypeIcons,
...messageTypeIcons,
};
+export type PredefinedIcon = keyof typeof definitions;
+
const extractAllIcons = (icons: Icon[]) => icons.map(icon => {
switch (icon.type) {
case "simple":
@@ -122,11 +124,11 @@ library.add(...extractAllIcons(Object.values(definitions)));
})
export class UiIcon extends Vue {
@Prop({
- type: [ String, Object ],
+ type: [String, Object],
validator: value => typeof value === "object" || Object.keys(definitions).includes(value),
required: true,
})
- icon: string | IconDefinition;
+ icon: PredefinedIcon | IconDefinition;
get definition(): Icon {
return typeof this.icon === "string"
diff --git a/resources/ts/store/favourites.ts b/resources/ts/store/favourites.ts
index 0f61f68..94f608e 100644
--- a/resources/ts/store/favourites.ts
+++ b/resources/ts/store/favourites.ts
@@ -1,6 +1,7 @@
import { RootState } from "./root";
import { Module } from "vuex";
import { Stop } from "../model";
+import { except } from "../utils";
export interface Favourite {
id: string;
@@ -19,7 +20,13 @@ const favourites: Module = {
},
mutations: {
add(state, favourite: Favourite) {
- state.favourites.push(favourite);
+ const existing = state.favourites.find((current: Favourite) => current.name === favourite.name);
+
+ if (!existing) {
+ state.favourites.push(favourite);
+ }
+
+ Object.assign(existing, except(favourite, ["id"]));
},
remove(state, favourite: Favourite) {
state.favourites = state.favourites.filter(f => f != favourite);
diff --git a/resources/ts/utils.ts b/resources/ts/utils.ts
index d7d6a22..213ee92 100644
--- a/resources/ts/utils.ts
+++ b/resources/ts/utils.ts
@@ -38,6 +38,14 @@ export function filter(source: T, filter: (value: T[KT],
return result;
}
+export function except(source: T, keys: (keyof T)[]) {
+ return filter(source, (_, key) => !keys.includes(key))
+}
+
+export function only(source: T, keys: (keyof T)[]) {
+ return filter(source, (_, key) => keys.includes(key))
+}
+
export function signed(number: number): string {
return number > 0 ? `+${number}` : number.toString();
}