Skip to content

Commit

Permalink
Merge pull request #441 from icssc/events-connect
Browse files Browse the repository at this point in the history
Events connect
  • Loading branch information
bjsilva1 authored May 21, 2024
2 parents ab96dc5 + 85ab758 commit bf22e74
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 45 deletions.
18 changes: 18 additions & 0 deletions apps/expo/src/app/events/_layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Stack } from "expo-router"
import { EventsProvider } from "./eventsContext"

export default function EventsLayout() {
return (
<EventsProvider>
<Stack>
<Stack.Screen name="index" options={{
headerShown: false
}}/>
<Stack.Screen name="event/[id]" options={{
headerBackTitle: "Events",
headerTitleStyle: { color: "white" },
}}/>
</Stack>
</EventsProvider>
)
}
35 changes: 13 additions & 22 deletions apps/expo/src/app/events/event/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useContext } from "react";
import { Stack, useGlobalSearchParams } from "expo-router";
import {
CalendarClock,
Expand All @@ -24,28 +24,19 @@ import type { Event } from "@zotmeal/db";

import { useMenuStore } from "~/utils";

import { useEvents } from "../eventsContext";

export default function Event() {
const { id } = useGlobalSearchParams();
const { selectedRestaurant } = useMenuStore();

const testData = {
title: "Test Event",
start: new Date("2022-01-01 12:00:00"),
end: new Date(),
image:
"https://uci.campusdish.com/-/media/Feature/Articles/DefaultEventImage.ashx?mh=350&mw=350&hash=B788068F09F0E38D1D19756934E293E4C1379BBF",
shortDescription: "This is a test event with a short description!",
longDescription: `This is a long description of the event. It's so long that it wraps around multiple lines. It's a very long description, but it's also very interesting. You should definitely read it.`,
restaurantId: "3314",
} satisfies Event;
const { events } = useEvents()
const eventData = events[Number(id)]!

return (
<>
<Stack.Screen
options={{
headerTitle: testData.title,
headerBackTitle: "Events",
headerTitleStyle: { color: "white" },
headerTitle: eventData.title
}}
/>
<ScrollView
Expand All @@ -70,15 +61,15 @@ export default function Event() {
<Image
resizeMode="contain"
source={{
uri: testData.image ?? require("../example-event-image.png"),
uri: eventData.image ?? require("../example-event-image.png"),
}}
minWidth={100}
maxWidth="100%"
height={200}
/>
</YStack>
<YStack padding={0} gap="$2" marginVertical="$4">
<H3>{testData.title}</H3>
<YStack padding={20} gap="$2" marginVertical="$4">
<H3>{eventData.title}</H3>
<Separator marginBottom="$2" />
<XStack alignItems="center" padding={0} gap="$2">
<MapPin />
Expand All @@ -90,13 +81,13 @@ export default function Event() {
<XStack alignItems="center" padding={0} gap="$2">
<CalendarClock />
<Text>
{format(testData.start.toString(), "LLL do p")} -{" "}
{format(testData.end.toString(), "LLL do p")}
{format(eventData.start.toString(), "LLL do p")} -{" "}
{format(eventData.end.toString(), "LLL do p")}
</Text>
</XStack>
<XStack alignItems="center" padding={0} gap="$2">
<Info />
<Text>{testData.shortDescription}</Text>
<Text>{eventData.shortDescription}</Text>
</XStack>
</YStack>
<Accordion overflow="hidden" width="95%" type="multiple">
Expand Down Expand Up @@ -124,7 +115,7 @@ export default function Event() {
borderTopLeftRadius={0}
borderTopRightRadius={0}
>
<Paragraph>{testData.longDescription}</Paragraph>
<Paragraph>{eventData.longDescription}</Paragraph>
</Accordion.Content>
</Accordion.Item>
</Accordion>
Expand Down
24 changes: 24 additions & 0 deletions apps/expo/src/app/events/eventsContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, { createContext, useState, useContext, ReactNode } from 'react';
import type { Event } from "@zotmeal/db"

interface EventsContextProps {
events: Event[];
setEvents: React.Dispatch<React.SetStateAction<Event[]>>;
}

const EventsContext = createContext<EventsContextProps>({events: [], setEvents: () => {}});

export function EventsProvider(props: { children: ReactNode }) {
const [events, setEvents] = useState<Event[]>([]);

return (
<EventsContext.Provider value={{ events, setEvents }}>
{props.children}
</EventsContext.Provider>
);
};

export function useEvents() {
const context = useContext(EventsContext);
return context;
};
57 changes: 35 additions & 22 deletions apps/expo/src/app/events/index.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,49 @@
import { useEffect} from "react";
import { Link } from "expo-router";
import { format } from "date-fns";
import { H3, Image, ScrollView, Text, YStack } from "tamagui";

import type { Event } from "@zotmeal/db";
import { useEvents } from "./eventsContext";

import { RestaurantTabs } from "~/components";

// import { api } from "~/utils/api";
import { api } from "~/utils/api";


// Create a context for events, default value is a test event
const testData: Event = {
start: new Date("2022-01-01 12:00:00"),
end: new Date(),
title: "Test Event",
shortDescription: "This is a test event",
longDescription: `This is a long description of the event. It's so long that it wraps
around multiple lines. It's a very long description, but it's also
very interesting. You should definitely read it.`,
image:
"https://uci.campusdish.com/-/media/Feature/Articles/DefaultEventImage.ashx?mh=350&mw=350&hash=B788068F09F0E38D1D19756934E293E4C1379BBF",
restaurantId: "3314",
} satisfies Event;

// Events Component
export default function Events() {
// const { data, error } = api.event.get.useQuery({});
const { events, setEvents } = useEvents();

const eventsQuery = api.event.get.useQuery({});

const testData: Event[] = Array(5).fill({
start: new Date("2022-01-01 12:00:00"),
end: new Date(),
title: "Test Event",
shortDescription: "This is a test event",
longDescription: `This is a long description of the event. It's so long that it wraps
around multiple lines. It's a very long description, but it's also
very interesting. You should definitely read it.`,
image:
"https://uci.campusdish.com/-/media/Feature/Articles/DefaultEventImage.ashx?mh=350&mw=350&hash=B788068F09F0E38D1D19756934E293E4C1379BBF",
restaurantId: "3314",
} satisfies Event) as Event[];
useEffect(() => {
if (eventsQuery?.data) {
setEvents(eventsQuery.data);
}
}, [eventsQuery?.data]);

// if (!data) {
// return <Text>Loading...</Text>;
// }
if (eventsQuery?.isLoading) {
return <Text>Loading...</Text>;
}

// if (error) {
// return <Text>Error: {error.message}</Text>;
// }
if (eventsQuery?.isError) {
return <Text>Error: {eventsQuery.error.message}</Text>;
}
return (
<RestaurantTabs>
<ScrollView
Expand All @@ -39,12 +52,12 @@ export default function Events() {
bottom: 200,
}}
>
{testData.map((event: Event, index: number) => (
{events.map((event: Event, index: number) => (
<Link
key={index}
href={{
pathname: "/events/event/[id]",
params: { id: 2 },
params: { id: index },
}}
asChild
>
Expand Down
19 changes: 18 additions & 1 deletion packages/api/src/events/services/scrape.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import axios from "axios";
import * as cheerio from "cheerio";

import type { Event } from "@zotmeal/db";
import type { Event, Drizzle } from "@zotmeal/db";
import { EventSchema } from "@zotmeal/db";
import { getRestaurantId, parseEventDate } from "@zotmeal/utils";
import { upsertEvents } from "./event";

import { logger } from "../../../logger";

Expand Down Expand Up @@ -115,3 +116,19 @@ export async function scrapeEvents(html: string): Promise<Event[] | null> {
}
return null;
}

// scrapes all events from campusDish and upserts them into the db
export async function scrapeCampusDishEvents(db: Drizzle): Promise<Event[]> {
const html = await getHTML(
"https://uci-campusdish-com.translate.goog/api/events?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp",
);
const events = await scrapeEvents(html);

if (!events) {
throw new Error("Could not retrieve campus dish events");
}

const upsertedEvents = await upsertEvents(db, events);

return upsertedEvents
}
5 changes: 5 additions & 0 deletions packages/api/src/services/getWeekInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { z } from "zod";
import type { Drizzle } from "@zotmeal/db";
import { RestaurantSchema } from "@zotmeal/db";
import { DateRegex } from "@zotmeal/validators";
import { scrapeCampusDishEvents } from "../events";

import type { UpdateDailyParams } from "./updateDaily";
import { logger } from "../../logger";
Expand All @@ -24,6 +25,10 @@ export async function getWeekInfo(
const { date: dateString, restaurant } = params;
const startDate = new Date(dateString);

// Scrape and insert new events into db
const eventResults = await scrapeCampusDishEvents(db)

// Update menus for each day
const results = await Promise.allSettled(
Array.from({ length: NUM_DAYS_UPDATE }).map((_, i) => {
const insertDate = new Date();
Expand Down

0 comments on commit bf22e74

Please sign in to comment.