From ef7302ecd3d8b37a4f014194680f5a4e76552f9a Mon Sep 17 00:00:00 2001
From: Silvan Kisseleff <silvan.kisseleff@gmail.com>
Date: Tue, 29 Oct 2024 21:02:02 +0100
Subject: [PATCH 1/2] added dashboard view of all upcoming screenings with a
 dropdown select

---
 .../src/common/components/SecuredRoute.tsx    |  18 +++
 apps/frontend/src/index.css                   |  56 +--------
 apps/frontend/src/main.tsx                    |  10 +-
 .../src/pages/overview/overview.page.tsx      | 110 ++++++++++++++++++
 apps/frontend/src/translations/en.json        |   6 +
 5 files changed, 144 insertions(+), 56 deletions(-)
 create mode 100644 apps/frontend/src/common/components/SecuredRoute.tsx
 create mode 100644 apps/frontend/src/pages/overview/overview.page.tsx

diff --git a/apps/frontend/src/common/components/SecuredRoute.tsx b/apps/frontend/src/common/components/SecuredRoute.tsx
new file mode 100644
index 0000000..af3399e
--- /dev/null
+++ b/apps/frontend/src/common/components/SecuredRoute.tsx
@@ -0,0 +1,18 @@
+import { useNavigate, Outlet } from 'react-router-dom'
+import { getToken } from '../token.helper'
+import { useEffect } from 'react'
+
+function SecuredRoute() {
+  const token = getToken()
+  const navigate = useNavigate()
+
+  useEffect(() => {
+    if (token === null) {
+      navigate('/login')
+    }
+  }, [token, navigate])
+
+  return token ? <Outlet /> : null
+}
+
+export default SecuredRoute
diff --git a/apps/frontend/src/index.css b/apps/frontend/src/index.css
index 80b6306..eb6cd27 100644
--- a/apps/frontend/src/index.css
+++ b/apps/frontend/src/index.css
@@ -7,58 +7,4 @@
   text-rendering: optimizeLegibility;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
-}
-
-a {
-  font-weight: 500;
-  color: #646cff;
-  text-decoration: inherit;
-}
-a:hover {
-  color: #535bf2;
-}
-
-body {
-  margin: 0;
-  display: flex;
-  place-items: center;
-  min-width: 320px;
-  min-height: 100vh;
-}
-
-h1 {
-  font-size: 3.2em;
-  line-height: 1.1;
-}
-
-button {
-  border-radius: 8px;
-  border: 1px solid transparent;
-  padding: 0.6em 1.2em;
-  font-size: 1em;
-  font-weight: 500;
-  font-family: inherit;
-  background-color: #1a1a1a;
-  cursor: pointer;
-  transition: border-color 0.25s;
-}
-button:hover {
-  border-color: #646cff;
-}
-button:focus,
-button:focus-visible {
-  outline: 4px auto -webkit-focus-ring-color;
-}
-
-@media (prefers-color-scheme: light) {
-  :root {
-    color: #213547;
-    background-color: #ffffff;
-  }
-  a:hover {
-    color: #747bff;
-  }
-  button {
-    background-color: #f9f9f9;
-  }
-}
+}
\ No newline at end of file
diff --git a/apps/frontend/src/main.tsx b/apps/frontend/src/main.tsx
index 2e478a3..de6c436 100644
--- a/apps/frontend/src/main.tsx
+++ b/apps/frontend/src/main.tsx
@@ -10,6 +10,8 @@ import './index.css'
 import client from './common/apolloClient.ts'
 import Register from './pages/register/register.page.tsx'
 import Login from './pages/login/login.page.tsx'
+import Overview from './pages/overview/overview.page.tsx'
+import SecuredRoute from './common/components/SecuredRoute.tsx'
 
 const router = createBrowserRouter([
   {
@@ -22,7 +24,13 @@ const router = createBrowserRouter([
   },
   {
     path: '/',
-    element: <div>Hello world!</div>,
+    element: <SecuredRoute />,
+    children: [
+      {
+        index: true,
+        element: <Overview />,
+      },
+    ],
   },
 ])
 
diff --git a/apps/frontend/src/pages/overview/overview.page.tsx b/apps/frontend/src/pages/overview/overview.page.tsx
new file mode 100644
index 0000000..8d6eded
--- /dev/null
+++ b/apps/frontend/src/pages/overview/overview.page.tsx
@@ -0,0 +1,110 @@
+import { useQuery } from '@apollo/client'
+import { useTranslation } from 'react-i18next'
+import { graphql } from '../../gql'
+import { Screenings_And_LocationsQuery } from '../../gql/graphql'
+import {
+  Autocomplete,
+  Box,
+  Card,
+  CardContent,
+  CardMedia,
+  Skeleton,
+  TextField,
+  Typography,
+} from '@mui/material'
+import { useState } from 'react'
+
+const SCREENINGS_AND_LOCATIONS = graphql(`
+  query SCREENINGS_AND_LOCATIONS($id: Int) {
+    screenings(
+      where: { hall: { is: { location: { is: { id: { equals: $id } } } } } }
+    ) {
+      id
+      hall {
+        name
+        location {
+          name
+        }
+      }
+      movie {
+        title
+        posterURL
+      }
+    }
+    locations {
+      id
+      name
+    }
+  }
+`)
+
+function Overview() {
+  const { t } = useTranslation()
+  const [value, setValue] = useState<{ id: number; label: string } | null>(null)
+
+  const { data, loading } = useQuery<Screenings_And_LocationsQuery>(
+    SCREENINGS_AND_LOCATIONS,
+    {
+      variables: {
+        id: value?.id,
+      },
+    }
+  )
+
+  console.log(value)
+
+  return (
+    <Box>
+      <Typography variant="h1">{t('overview.title')}</Typography>
+      <Box
+        sx={{
+          marginBottom: 5,
+        }}
+      >
+        <Autocomplete
+          value={value}
+          onChange={(event, newValue) => {
+            setValue(newValue)
+          }}
+          options={
+            data?.locations.map((l) => ({ label: l.name, id: l.id })) || []
+          }
+          renderInput={(params) => (
+            <TextField {...params} label={t('overview.locations.label')} />
+          )}
+        />
+      </Box>
+      <Box
+        sx={{
+          display: 'grid',
+          gridTemplateColumns:
+            'repeat(auto-fill, minmax(calc(20% - 20px), 1fr))',
+          gap: 2,
+        }}
+      >
+        {loading && (
+          <>
+            <Skeleton height={500} width={250} />
+            <Skeleton height={500} width={250} />
+            <Skeleton height={500} width={250} />
+            <Skeleton height={500} width={250} />
+          </>
+        )}
+
+        {data?.screenings.map((screening) => (
+          <Card key={screening.id}>
+            <CardMedia component="img" image={screening.movie.posterURL} />
+            <CardContent>
+              <Typography variant="h6">{screening.movie.title}</Typography>
+              <Typography variant="subtitle1">
+                {screening.hall.location.name} - {screening.hall.name}
+              </Typography>
+            </CardContent>
+          </Card>
+        ))}
+      </Box>
+    </Box>
+  )
+}
+
+export default Overview
diff --git a/apps/frontend/src/translations/en.json b/apps/frontend/src/translations/en.json
index 56ea1ec..1585ddc 100644
--- a/apps/frontend/src/translations/en.json
+++ b/apps/frontend/src/translations/en.json
@@ -28,5 +28,11 @@
       "required": "Password is required"
     },
     "submit": "login"
+  },
+  "overview": {
+    "title": "Movies",
+    "locations": {
+      "label": "Select Location"
+    }
   }
 }
-- 
GitLab


From 1c24328b34fb8344b71d7ba4a05cb819c895a681 Mon Sep 17 00:00:00 2001
From: Silvan Kisseleff <silvan.kisseleff@gmail.com>
Date: Tue, 29 Oct 2024 21:03:37 +0100
Subject: [PATCH 2/2] run formatter

---
 apps/frontend/src/index.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/frontend/src/index.css b/apps/frontend/src/index.css
index eb6cd27..9133d7f 100644
--- a/apps/frontend/src/index.css
+++ b/apps/frontend/src/index.css
@@ -7,4 +7,4 @@
   text-rendering: optimizeLegibility;
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
-}
\ No newline at end of file
+}
-- 
GitLab