Skip to content

Commit

Permalink
🧱 migrate to GraphQL (#420)
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Eggl <[email protected]>
Co-authored-by: Robert Eggl <[email protected]>
  • Loading branch information
BuildmodeOne and Robert27 authored Sep 20, 2024
1 parent 34838de commit b2334c1
Show file tree
Hide file tree
Showing 32 changed files with 743 additions and 1,458 deletions.
63 changes: 63 additions & 0 deletions rogue-thi-app/components/cards/AnnouncementPrompt.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react'

import Button from 'react-bootstrap/Button'
import Card from 'react-bootstrap/Card'

import { ExternalLink, Megaphone, X } from 'lucide-react'

import Link from 'next/link'
import styles from '../../styles/Home.module.css'
import { useTranslation } from 'next-i18next'

/**
* Introduction event notification card.
* @param {object} onHide Invoked when the user wants to hide the prompt
*/
export default function AnnouncementPrompt({ announcement, onHide }) {
const { i18n, t } = useTranslation(['common'])
const locale = i18n.languages[0]

return (
<Card className={styles.card}>
<Card.Body>
<Card.Title className={styles.cardTitle}>
<Megaphone size={22} />
<span className={styles.cardTitleText}>
{announcement.title[locale]}
</span>
<Button
variant="link"
className={styles.cardButton}
onClick={() => onHide()}
>
<X size={22} />
</Button>
</Card.Title>
<Card.Text>
<p>{announcement.description[locale]}</p>
</Card.Text>

{announcement.url && (
<Link
href={announcement.url}
passHref
>
<Button
target="_blank"
variant="link"
style={{
display: 'flex',
alignItems: 'center',
gap: '0.5rem',
maxWidth: 'fit-content',
}}
>
{t('cards.announcements.readMore')}
<ExternalLink size={16} />
</Button>
</Link>
)}
</Card.Body>
</Card>
)
}
2 changes: 1 addition & 1 deletion rogue-thi-app/components/cards/EventsCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default function EventsCard() {
async function load() {
try {
const events = await NeulandAPI.getCampusLifeEvents()
setCalendar(events)
setCalendar(events.clEvents)
} catch (e) {
// directly notifying the user about the error is not necessary here
console.error(e)
Expand Down
21 changes: 12 additions & 9 deletions rogue-thi-app/components/cards/FoodCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,23 @@ export default function FoodCard() {

useEffect(() => {
async function load() {
const restaurants = localStorage.selectedRestaurants
? JSON.parse(localStorage.selectedRestaurants)
: ['mensa']
const restaurants = localStorage.selectedRestaurantList
? JSON.parse(localStorage.selectedRestaurantList)
: ['IngolstadtMensa']
if (restaurants.length !== 1) {
setFoodCardTitle('food')
} else {
switch (restaurants[0]) {
case 'mensa':
setFoodCardTitle('cafeteria')
case 'IngolstadtMensa':
setFoodCardTitle('mensaIngolstadt')
break
case 'reimanns':
case 'NeuburgMensa':
setFoodCardTitle('mensaNeuburg')
break
case 'Reimanns':
setFoodCardTitle('reimanns')
break
case 'canisius':
case 'Canisius':
setFoodCardTitle('canisius')
break
default:
Expand All @@ -73,14 +76,14 @@ export default function FoodCard() {
}
}

const entries = await loadFoodEntries(restaurants)
const entries = await loadFoodEntries(restaurants, false)
const todayEntries = entries
.find((x) => x.timestamp === today)
?.meals.filter(
(x) =>
x.category !== 'soup' &&
x.category !== 'salad' &&
selectedRestaurants.includes(x.restaurant.toLowerCase())
selectedRestaurants.includes(x.restaurant)
)

todayEntries?.sort((a, b) => userMealRating(b) - userMealRating(a))
Expand Down
2 changes: 1 addition & 1 deletion rogue-thi-app/components/cards/MobilityCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export default function MobilityCard() {
customPlaceholder={placeholder}
>
<ListGroup variant="flush">
{mobility &&
{mobility !== null &&
mobility.slice(0, 4).map((entry, i) => (
<ListGroup.Item
key={i}
Expand Down
44 changes: 30 additions & 14 deletions rogue-thi-app/components/modal/FilterFoodModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ export default function FilterFoodModal() {
saveAllergenSelection,
showFoodFilterModal,
setShowFoodFilterModal,
showStaticMeals,
toggleShowStaticMeals,
} = useFoodFilter()
const [showAllergenSelection, setShowAllergenSelection] = useState(false)
const [showPreferencesSelection, setShowPreferencesSelection] =
Expand Down Expand Up @@ -61,28 +63,42 @@ export default function FilterFoodModal() {

<div className={styles.filterBody}>
<Form.Check
id="restaurant-checkbox-mensa"
label={t('food.filterModal.restaurants.showMensa')}
checked={selectedRestaurants.includes('mensa')}
onChange={() => toggleSelectedRestaurant('mensa')}
id="restaurant-checkbox-mensa-ingolstadt"
label={t('food.filterModal.restaurants.showMensaIngolstadt')}
checked={selectedRestaurants.includes('IngolstadtMensa')}
onChange={() => toggleSelectedRestaurant('IngolstadtMensa')}
/>
<Form.Check
id="restaurant-checkbox-reimanns"
label={t('food.filterModal.restaurants.showReimanns')}
checked={selectedRestaurants.includes('reimanns')}
onChange={() => toggleSelectedRestaurant('reimanns')}
id="restaurant-checkbox-mensa-neuburg"
label={t('food.filterModal.restaurants.showMensaNeuburg')}
checked={selectedRestaurants.includes('NeuburgMensa')}
onChange={() => toggleSelectedRestaurant('NeuburgMensa')}
/>
<Form.Check
id="restaurant-checkbox-reimanns-static"
label={t('food.filterModal.restaurants.showReimannsStatic')}
checked={selectedRestaurants.includes('reimanns-static')}
onChange={() => toggleSelectedRestaurant('reimanns-static')}
id="restaurant-checkbox-reimanns"
label={t('food.filterModal.restaurants.showReimanns')}
checked={selectedRestaurants.includes('Reimanns')}
onChange={() => toggleSelectedRestaurant('Reimanns')}
/>
<Form.Check
id="restaurant-checkbox-canisius"
label={t('food.filterModal.restaurants.showCanisius')}
checked={selectedRestaurants.includes('canisius')}
onChange={() => toggleSelectedRestaurant('canisius')}
checked={selectedRestaurants.includes('Canisius')}
onChange={() => toggleSelectedRestaurant('Canisius')}
/>
</div>

<hr />
<div className={styles.filterHeader}>
<h6>{t('food.filterModal.showStaticMeals.title')}</h6>
</div>

<div className={styles.filterBody}>
<Form.Check
id="show-static-meals-checkbox"
label={t('food.filterModal.showStaticMeals.label')}
checked={showStaticMeals}
onChange={() => toggleShowStaticMeals()}
/>
</div>

Expand Down
53 changes: 10 additions & 43 deletions rogue-thi-app/lib/backend-utils/food-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,46 +15,11 @@ const VERSIONS = ['v1', 'v2']
* @returns {object[]}
*/
export async function loadFoodEntries(
restaurants = ['mensa', 'reimanns', 'reimanns-static', 'canisius']
restaurants = ['IngolstadtMensa', 'NeuburgMensa', 'Reimanns', 'Canisius'],
showStaticMeals = false
) {
const entries = []

if (restaurants.includes('mensa')) {
try {
const data = await NeulandAPI.getMensaPlan()
entries.push(data)
} catch (e) {
console.error(e)
}
}

if (restaurants.some((x) => ['reimanns', 'reimanns-static'].includes(x))) {
try {
const data = await NeulandAPI.getReimannsPlan()
const startOfToday = new Date(formatISODate(new Date())).getTime()
const filteredData = data.filter(
(x) => new Date(x.timestamp).getTime() >= startOfToday
)

entries.push(filteredData)
} catch (e) {
console.error(e)
}
}

if (restaurants.includes('canisius')) {
try {
const data = await NeulandAPI.getCanisiusPlan()
const startOfToday = new Date(formatISODate(new Date())).getTime()
const filteredData = data.filter(
(x) => new Date(x.timestamp).getTime() >= startOfToday
)

entries.push(filteredData)
} catch (e) {
console.error(e)
}
}
const data = await NeulandAPI.getFoodPlan(restaurants)
const entries = data.food.foodData

// get start of this week (monday) or next monday if isWeekend
const startOfThisWeek = getMonday(getAdjustedDay(new Date()))
Expand All @@ -74,12 +39,14 @@ export async function loadFoodEntries(

// map entries to daysTest
return days.map((day) => {
const dayEntries = entries.flatMap(
(r) => r.find((x) => x.timestamp === day)?.meals || []
)
const dayEntry = entries.find((r) => r.timestamp === day)
return {
timestamp: day,
meals: dayEntries,
meals: dayEntry
? showStaticMeals
? dayEntry.meals
: dayEntry.meals.filter((meal) => !meal.static)
: [],
}
})
}
Expand Down
72 changes: 21 additions & 51 deletions rogue-thi-app/lib/backend-utils/mobility-utils.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { LockKeyhole } from 'lucide-react'
import { TextBlock } from 'react-placeholder/lib/placeholders'

import { formatFriendlyTime, formatRelativeMinutes } from '../date-utils'
import API from '../backend/authenticated-api'
import NeulandAPI from '../backend/neuland-api'

import stations from '../../data/mobility.json'
Expand Down Expand Up @@ -50,26 +49,6 @@ export function getMobilityLabel(kind, station, t) {
}
}

/**
* Fetches and parses parking availability for the campus
* @returns {object}
*/
async function getAndConvertCampusParkingData() {
let available = null
try {
const entries = await API.getCampusParkingData()
available = entries.find((x) => x.name === 'TG Gießerei Hochschule')?.free
available = typeof available === 'string' ? parseInt(available) : null
} catch (e) {
available = null
}

return {
name: 'Congressgarage',
available,
}
}

/**
* Fetches and parses mobility data
* @param {string} kind Mobility type (`bus`, `train`, `parking` or `charging`)
Expand All @@ -78,35 +57,20 @@ async function getAndConvertCampusParkingData() {
*/
export async function getMobilityEntries(kind, station) {
if (kind === 'bus') {
return NeulandAPI.getBusPlan(station)
const data = await NeulandAPI.getBusPlan(station)
return data.bus
} else if (kind === 'train') {
return NeulandAPI.getTrainPlan(station)
const data = await NeulandAPI.getTrainPlan(station)
return data.train
} else if (kind === 'parking') {
const [data, campusEntry] = await Promise.all([
NeulandAPI.getParkingData(),
getAndConvertCampusParkingData(),
])
data.push(campusEntry)

return [
...stations.parking.map((x) => {
const entry = data.find((y) => x.name === y.name)
return {
name: x.name,
priceLevel: x.priceLevel,
available: entry ? entry.available : null,
}
}),
...data.filter((x) => !stations.parking.find((y) => x.name === y.name)),
]
const data = await NeulandAPI.getParkingData()
return data.parking.lots
} else if (kind === 'charging') {
const data = await NeulandAPI.getCharingStationData()
return [
...stations.charging
.map((x) => data.find((y) => x.id === y.id))
.filter((x) => !!x),
...data.filter((x) => !stations.charging.find((y) => x.id === y.id)),
const relevantStations = [
59362, 59340, 59360, 59358, 59356, 59200, 59354, 1770740, 22532,
]
return data.charging.filter((x) => relevantStations.includes(x.id))
} else {
throw new Error('Invalid mobility kind ' + kind)
}
Expand Down Expand Up @@ -193,11 +157,17 @@ export function RenderMobilityEntry({ kind, item, maxLen, styles, detailed }) {
)}
<div className={styles.mobilityDestination}>{item.name}</div>
<div className={styles.mobilityTime}>
{typeof item.available === 'number'
? t('transport.details.parking.available', {
available: item.available,
})
: t('transport.details.parking.unknown')}
{item.available && item.total ? (
<span>
{t('transport.details.parking.available', {
available: `${Math.round(
((item.total - item.available) / item.total) * 100
)}% - ${item.available}`,
})}
</span>
) : (
<span>{t('transport.details.parking.unknown')}</span>
)}
</div>
</>
)
Expand Down Expand Up @@ -228,7 +198,7 @@ export function RenderMobilityEntry({ kind, item, maxLen, styles, detailed }) {
function formatTimes(time, cardMin, detailedMin) {
const cardMs = cardMin * 60 * 1000
const detailedMs = detailedMin * 60 * 1000
const actualTime = new Date(time)
const actualTime = new Date(Number(time))
const timeDifference = actualTime - new Date()
let timeString

Expand Down
Loading

0 comments on commit b2334c1

Please sign in to comment.