Skip to content

Commit

Permalink
implement pommes probability with pommes-o-meter
Browse files Browse the repository at this point in the history
  • Loading branch information
TheBlackbird14 committed May 31, 2024
1 parent 9790468 commit 58ed28c
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 18 deletions.
86 changes: 81 additions & 5 deletions src/components/foodCarousel.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
<script setup lang="ts">
import apiService from '@/scripts/api.service'
import FoodCarouselItem from '@/components/foodCarouselItem.vue'
import { onBeforeMount, reactive } from 'vue'
import { customRef, onBeforeMount, reactive, ref } from 'vue'

Check warning on line 4 in src/components/foodCarousel.vue

View workflow job for this annotation

GitHub Actions / lint

'customRef' is defined but never used
import type { foodScheduleEntry } from '@/scripts/types/food-schedule.interface'
import PommesOMeter from '@/components/pommesOMeter.vue'
const foodSchedule = reactive({
FoodScheduleItems: [] as foodScheduleEntry[]
})
let percentage = 0
let currentItem = ref(0)
onBeforeMount(() => {
getFoodSchedule()
})
Expand All @@ -17,6 +22,17 @@ function getFoodSchedule() {
response.forEach((foodScheduleEntry) => {
foodSchedule.FoodScheduleItems.push(foodScheduleEntry)
})
const today = new Date()
const todaysEntry = foodSchedule.FoodScheduleItems.find((entry) => {
return entry.date.getDate() === today.getDate()
})
if (todaysEntry) {
const percentages = todaysEntry.probability
percentage = Math.round(percentages.reduce((a, b) => a + b, 0) / percentages.length)
currentItem.value = foodSchedule.FoodScheduleItems.indexOf(todaysEntry)
}
})
}
Expand All @@ -27,20 +43,80 @@ function colClass(date: Date) {
return 'col'
}
}
const mobileWidth = ref(window.screen.width <= 767)
window.addEventListener('resize', () => {
mobileWidth.value = window.screen.width <= 767
})
function changeItem(newItem: number) {
if (newItem < foodSchedule.FoodScheduleItems.length && newItem >= 0) {
currentItem.value = newItem
}
const percentages = foodSchedule.FoodScheduleItems[currentItem.value].probability
percentage = Math.round(percentages.reduce((a, b) => a + b, 0) / percentages.length)
}
</script>

<template>
<div class="container mt-lg-5">
<div class="row">
<div class="container">
<div v-if="!mobileWidth" class="row">
<div
v-for="(foodScheduleEntry, key) in foodSchedule.FoodScheduleItems"
:key="key"
:class="colClass(foodScheduleEntry.date)"
>
<food-carousel-item :food-entry="foodScheduleEntry"></food-carousel-item>
<food-carousel-item
:food-entry="foodScheduleEntry"
@select="changeItem(key)"
:selected="currentItem === key"
></food-carousel-item>
</div>
</div>

<div
v-else
class="d-flex flex-row align-items-center justify-content-center"
style="width: 80%; margin: auto"
>
<i
class="bi bi-caret-left"
style="font-size: 200%; cursor: pointer"
@click="changeItem(currentItem - 1)"
:class="{ faded: currentItem === 0 }"
></i>
<food-carousel-item
:food-entry="foodSchedule.FoodScheduleItems[currentItem]"
></food-carousel-item>
<i
class="bi bi-caret-right"
style="font-size: 200%; cursor: pointer"
@click="changeItem(currentItem + 1)"
:class="{ faded: currentItem === foodSchedule.FoodScheduleItems.length - 1 }"
></i>
</div>
</div>

<pommes-o-meter v-if="percentage" class="o-meter" :percentage="percentage"></pommes-o-meter>
</template>

<style scoped></style>
<style scoped>
.container {
margin-top: 2rem;
}
i {
color: var(--text-primary-color);
}
.faded {
opacity: 0.5;
}
.o-meter {
text-align: center;
margin-top: 2rem;
}
</style>
32 changes: 22 additions & 10 deletions src/components/foodCarouselItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ const props = defineProps({
foodEntry: {
type: Object as PropType<foodScheduleEntry>,
required: true
},
selected: {
type: Boolean,
required: false,
default: false
}
})
const emit = defineEmits(['select'])
function getWeekDay(date: Date) {
const weekdays = ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag']
Expand All @@ -26,26 +33,26 @@ function dateToString(date: Date) {
}
const cardClass = computed(() => {
/*
* sorry for the wierd if statement
* basically it just checks if either
*
* */
let cardClass = 'card'
if (
(props.foodEntry?.date.getDate() === new Date().getDate() &&
props.foodEntry.date > new Date()) ||
(props.foodEntry?.date.getDate() === new Date().getDate() + 1 &&
props.foodEntry.date.getHours() + 1 < new Date().getHours())
) {
return 'card card-active'
} else {
return 'card'
cardClass += ' card-active'
}
if (props.selected) {
cardClass += ' card-selected'
}
return cardClass
})
</script>

<template>
<div :class="cardClass">
<div :class="cardClass" @click="emit('select')">
<div class="card-header">
<h2 class="card-title text-center">{{ getWeekDay(props.foodEntry.date) }}</h2>
<h4 class="card-subtitle mb-2 text-center">{{ dateToString(props.foodEntry.date) }}</h4>
Expand Down Expand Up @@ -74,6 +81,11 @@ p {
}
.card-active {
background-color: var(--background-color-primary);
border-bottom: 5px solid rgb(245, 146, 47);
}
.card-selected {
border-color: cornflowerblue;
border-width: 1px;
}
</style>
80 changes: 80 additions & 0 deletions src/components/pommesOMeter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<script setup lang="ts">
import { computed, ref } from 'vue'

Check warning on line 2 in src/components/pommesOMeter.vue

View workflow job for this annotation

GitHub Actions / lint

'ref' is defined but never used
const props = defineProps({
percentage: {
type: Number,
required: true
}
})
const meterPath = computed(() => {
const radius = 135
const startAngle = 135
const endAngle = startAngle + (props.percentage / 100) * 270
const x1 = 150 + radius * Math.cos((Math.PI / 180) * startAngle)
const y1 = 150 + radius * Math.sin((Math.PI / 180) * startAngle)
const x2 = 150 + radius * Math.cos((Math.PI / 180) * endAngle)
const y2 = 150 + radius * Math.sin((Math.PI / 180) * endAngle)
const largeArcFlag = endAngle - startAngle <= 180 ? 0 : 1
return `M ${x1} ${y1} A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2}`
})
const meterColor = computed(() => {
const hue = (props.percentage * 120) / 100 // 0 (red) to 120 (green)
return `hsl(${hue}, 100%, 50%)`
})
const probabilityText = computed(() => {
if (props.percentage < 20) {
return 'unwahrscheinlich Sehr'
} else if (props.percentage < 40) {
return 'Unwahrscheinlich'
} else if (props.percentage < 60) {
return 'Möglich'
} else if (props.percentage < 80) {
return 'Wahrscheinlich'
} else {
return 'wahrscheinlich Sehr '
}
})
</script>

<template>
<div class="o-meter d-flex justify-content-center align-items-center">
<svg width="300" height="300" viewBox="0 0 300 300">
<circle
cx="150"
cy="150"
r="135"
stroke="#ddd"
stroke-width="20"
fill="none"
stroke-dasharray="636.172 212.057"
stroke-dashoffset="530.143"
stroke-linecap="round"
/>
<path
:d="meterPath"
:stroke="meterColor"
stroke-width="20"
fill="none"
stroke-linecap="round"
/>
<text x="50%" y="40%" text-anchor="middle" dy=".3em" font-size="45">{{ percentage }}%</text>
<text x="50%" y="60%" text-anchor="middle" dy=".3em" font-size="60">🍟</text>
<text x="50%" y="83%" text-anchor="middle" dy=".3em" font-size="19.5">
<tspan x="50%" dy="">{{ probabilityText.split(' ')[0] }}</tspan>
<tspan v-if="probabilityText.split(' ')[1]" x="50%" dy="-1em">
{{ probabilityText.split(' ')[1] }}
</tspan>
</text>
</svg>
</div>
</template>

<style scoped>
text {
fill: var(--text-primary-color);
}
</style>
9 changes: 6 additions & 3 deletions src/scripts/api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,18 @@ class ApiService {
const foodSchedule: foodScheduleEntry[] = []

data.forEach((element) => {
const newHomework: foodScheduleEntry = {
const newFood: foodScheduleEntry = {
id: element.id,
text: element.text,
date: new Date(element.date)
date: new Date(element.date),
probability: element.probability
}

foodSchedule.push(newHomework)
foodSchedule.push(newFood)
})

foodSchedule.sort((a, b) => a.id - b.id)

return foodSchedule
} catch (e) {
console.error('Error fetching data: ', e)
Expand Down
1 change: 1 addition & 0 deletions src/scripts/types/food-schedule.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ interface foodScheduleEntry {
id: number
text: string
date: Date
probability: number[]
}

export type { foodScheduleEntry }

0 comments on commit 58ed28c

Please sign in to comment.