diff --git a/app/assets/styles/button.css b/app/assets/styles/button.css index ebc7ca1..c753472 100755 --- a/app/assets/styles/button.css +++ b/app/assets/styles/button.css @@ -13,9 +13,42 @@ transition: var(--transition-default); outline: none; border: none; - background: transparent; + background: var(--background); color: var(--color); + &.raised { + box-shadow: var(--box-shadow-z2); + padding: .5em 1.5em; + border-radius: var(--radius-default); + } + + &.text { + --background: transparent; + --color: var(--color-black); + padding: .5em 1.5em; + border-radius: var(--radius-default); + + &:hover { + --background: rgba(0, 0, 0, 0.05); + } + + &.danger { + --color: var(--color-red); + + &:hover { + --background: rgba(255, 0, 0, 0.1); + } + } + } + + &.round { + display: flex; + justify-content: center; + align-items: center; + border-radius: 100%; + padding: .5rem; + } + &.cta { background: var(--background); color: var(--color); diff --git a/app/assets/styles/formInput.css b/app/assets/styles/formInput.css index 44d228d..01d1092 100755 --- a/app/assets/styles/formInput.css +++ b/app/assets/styles/formInput.css @@ -9,16 +9,15 @@ & label { position: absolute; + font-size: .8em; + top: .3rem; left: .5rem; - font-size: 1.5em; - top: .7rem; transition: var(--transition-default); } & input { all: unset; width: calc(100% - 1rem); - font-size: 1.2em; padding: 1.3rem .5rem .5rem .5rem; background: var(--color-white); @@ -27,7 +26,7 @@ } } - &:has(input:invalid) { + &.error { border-color: var(--color-red); outline-width: 2px; } @@ -36,9 +35,6 @@ & input:not(:placeholder-shown) { & + label { color: var(--color-main); - font-size: 1em; - top: .3rem; - right: .5rem; } } } \ No newline at end of file diff --git a/app/assets/styles/general.css b/app/assets/styles/general.css index c206ecb..f6c2d70 100755 --- a/app/assets/styles/general.css +++ b/app/assets/styles/general.css @@ -10,6 +10,7 @@ --color-blue: #2e86de; --color-blue-dark: #1b4b7f; --color-grey: #c7c7c7; + --color-black: #333; --color-orange: #DE9C2F; @@ -127,4 +128,41 @@ body { .gap-default { gap: 1rem; +} + +.bg-blue { + background: var(--color-blue); +} + +.bg-white { + background: var(--color-white); +} + +.padding { + gap: 1rem; + padding: var(--padding-default); +} + +dialog { + top: 50%; + left: 50%; + width: 100vw; + transform: translate(-50%, -50%); + border: none; + border-radius: var(--radius-default); + + font-size: 1rem; + + & header { + justify-content: space-between; + align-items: center; + } + + & footer { + justify-content: space-between; + } + + &::backdrop { + background: rgba(0, 0, 0, 0.5); + } } \ No newline at end of file diff --git a/app/assets/styles/priceCard.css b/app/assets/styles/priceCard.css index 47acd68..3cef1ec 100755 --- a/app/assets/styles/priceCard.css +++ b/app/assets/styles/priceCard.css @@ -11,83 +11,60 @@ opacity: 0; } - &.folded { - grid-template-rows: auto 0fr auto; - } - & > header { color: var(--color-white); display: flex; justify-content: space-between; align-items: center; - font-size: 1.3em; + + & > .name-price { + display: flex; + gap: .5rem; + + & > span:nth-child(2)::before { + content: '•'; + margin-right: .5rem; + opacity: .5; + } + } & > .Button { color: var(--color-white); - border: 2px solid var(--color-white); } } - & aside { - overflow: hidden; - } - - & footer { - display: flex; - justify-content: space-between; - align-items: center; - - & > .Button.delete { - scale: 0; - } - - & > .Button.deletable { - scale: 1; - } - } - - & .padding { - gap: 1rem; - padding: var(--padding-default); - } - - & .bg-blue { - background: var(--color-blue); - } - - & .bg-white { - background: var(--color-white); - } - & .wrapper { display: flex; flex-direction: row; width: 100%; gap: 1rem; justify-content: space-between; + padding-top: 0; & > * { - flex-basis: 25%; - flex-grow: 1; + flex-basis: 10%; + flex-grow: 0; } & > .info { + color: var(--color-white); align-items: center; + gap: .25rem; & > .icon { - color: var(--color-blue-light); font-size: 2rem; padding: .2rem; } & > .price { - font-size: 1.2rem; + display: flex; + align-items: center; + gap: .5rem; } & > .pro { - font-size: .8rem; + font-size: .6rem; font-weight: bold; - color: var(--color-main-light); } } } diff --git a/app/components/Pp/FormInput.vue b/app/components/Pp/FormInput.vue index 66c8a94..32889d8 100755 --- a/app/components/Pp/FormInput.vue +++ b/app/components/Pp/FormInput.vue @@ -3,7 +3,7 @@ - {{ label }} + {{ label }} @@ -24,7 +24,6 @@ type Props = { required ?: boolean label : string id : string - uid : string } const { @@ -35,12 +34,9 @@ const { max, label, id, - uid, } = defineProps() const emit = defineEmits(['blur']) const text = defineModel() - -const makeId = () => `${id}_${uid}` diff --git a/app/components/Pp/PriceCard.vue b/app/components/Pp/PriceCard.vue index 0b495bb..63ea1b5 100755 --- a/app/components/Pp/PriceCard.vue +++ b/app/components/Pp/PriceCard.vue @@ -1,64 +1,42 @@ - {}" + class="PriceCard card bg-blue" + :class="{ deleting }" > - - {{ card.name || 'Kein Name' }} - - + + + {{ card.name || 'Kein Name' }} + {{ intl.format(card.price)}} + + + - - + - - {{ intl.format(ppr) }} + + + {{ intl.format(card.ppr) }} + Pro 1 - - {{ intl.format(pps) }} + + + {{ intl.format(card.pps) }} + Pro 10 - - {{ intl.format(ppl) }} + + + {{ intl.format(card.ppl) }} + Pro 100 - - + diff --git a/app/pages/index.vue b/app/pages/index.vue index cc1abb7..a6dba3f 100755 --- a/app/pages/index.vue +++ b/app/pages/index.vue @@ -1,4 +1,38 @@ + + + + {{ currentCardIndex! > -1 ? 'Bearbeiten' : 'Hinzufügen'}} + + + + + + + + + + + + + + + + + + + + @@ -27,7 +61,7 @@ aria-hidden="true" /> - + Hinzufügen @@ -40,6 +74,9 @@ import type { Button } from '../../shared/ButtonGroup' const currentSort = ref(0) const isDirty = ref(false) +const currentCard = ref() +const currentCardIndex = ref(-1) +const modal = useTemplateRef('modal') const createCard = (uuid : string) : Card => ({ uuid, @@ -57,23 +94,41 @@ const cards = useState('cards', () => [ createCard(crypto.randomUUID()), ]) -const addCard = () => { - cards.value.unshift(createCard(crypto.randomUUID())) +const addCard = (card : Card) => { + const price = calculate(card) + cards.value.unshift({ ...card, ...price }) isDirty.value = true } -const removeCard = (card : Card) => { - cards.value = cards.value.filter(element => element.uuid !== card.uuid) +const removeCard = (index : number) => { + cards.value.splice(index, 1) isDirty.value = true updateLocalStorage() } -const updateCard = (card : Card, index : number) => { - cards.value[index] = card +const updateCard = () => { + if (currentCardIndex.value === -1) { + addCard(currentCard.value!) + } + + const price = calculate(currentCard.value!) + const newCard = { ...currentCard.value!, ...price } + cards.value.splice(currentCardIndex.value, 1, newCard) isDirty.value = true updateLocalStorage() } +const openModal = (index ?: number) => { + modal.value?.showModal() + if (index !== undefined && index > -1) { + currentCardIndex.value = index + currentCard.value = { ...cards.value[index]! } + return + } + + currentCardIndex.value = -1 + currentCard.value = createCard(crypto.randomUUID()) +} const updateLocalStorage = () => { localStorage.setItem('cards', JSON.stringify(cards.value)) @@ -120,6 +175,14 @@ const sort = (index : number) => { isDirty.value = false } +const calculate = (card : Card) => { + const ppr = card.price / card.roles + const pps = (ppr / card.sheets) * 10 + const ppl = (pps / card.layers) * 10 + + return { ppr, pps, ppl } +} + onMounted(() => { const cardsFromStorage = JSON.parse(localStorage.getItem('cards') ?? '[]') cards.value = cardsFromStorage.length !== 0 ? cardsFromStorage : cards.value