From 651e8e263308ff96f4c2c8bb1f961b61b84d3d83 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Th=C3=A9o=20LUDWIG?= <contact@theoludwig.fr>
Date: Mon, 20 May 2024 15:05:34 +0200
Subject: [PATCH] feat: add about page

---
 app/application/_layout.tsx                   |   2 +-
 app/application/users/settings.tsx            |  36 +++-----
 app/authentication/_layout.tsx                |   9 ++
 app/authentication/about.tsx                  |  26 ++++++
 app/authentication/login.tsx                  |   1 +
 app/authentication/register.tsx               |   1 +
 app/index.tsx                                 |   2 +-
 .../assets/images/Universite-Strasbourg.png   | Bin 10812 -> 0 bytes
 .../react-native/components/About.tsx         |  81 ++++++++++++++++++
 utils/__tests__/version.test.ts               |  39 +++++++++
 utils/version.ts                              |   8 ++
 11 files changed, 181 insertions(+), 24 deletions(-)
 create mode 100644 app/authentication/about.tsx
 delete mode 100644 presentation/assets/images/Universite-Strasbourg.png
 create mode 100644 presentation/react-native/components/About.tsx
 create mode 100644 utils/__tests__/version.test.ts
 create mode 100644 utils/version.ts

diff --git a/app/application/_layout.tsx b/app/application/_layout.tsx
index 25796d7..67cad6f 100644
--- a/app/application/_layout.tsx
+++ b/app/application/_layout.tsx
@@ -8,7 +8,7 @@ const TabLayout: React.FC = () => {
   const { user } = useAuthentication()
 
   if (user == null) {
-    return <Redirect href="/authentication/login" />
+    return <Redirect href="/authentication/about" />
   }
 
   return (
diff --git a/app/application/users/settings.tsx b/app/application/users/settings.tsx
index 1a4b9f9..414f11a 100644
--- a/app/application/users/settings.tsx
+++ b/app/application/users/settings.tsx
@@ -1,7 +1,6 @@
-import { Text } from "react-native"
 import { Button } from "react-native-paper"
-import { SafeAreaView } from "react-native-safe-area-context"
 
+import { About } from "@/presentation/react-native/components/About"
 import { useAuthentication } from "@/presentation/react/contexts/Authentication"
 
 const SettingsPage: React.FC = () => {
@@ -12,26 +11,19 @@ const SettingsPage: React.FC = () => {
   }
 
   return (
-    <SafeAreaView
-      style={[
-        {
-          flex: 1,
-          alignItems: "center",
-          justifyContent: "center",
-        },
-      ]}
-    >
-      <Text>Settings</Text>
-
-      <Button
-        mode="contained"
-        onPress={handleLogout}
-        loading={logout.state === "loading"}
-        disabled={logout.state === "loading"}
-      >
-        Logout
-      </Button>
-    </SafeAreaView>
+    <About
+      actionButton={
+        <Button
+          mode="contained"
+          labelStyle={{ fontSize: 18 }}
+          onPress={handleLogout}
+          loading={logout.state === "loading"}
+          disabled={logout.state === "loading"}
+        >
+          Logout
+        </Button>
+      }
+    />
   )
 }
 
diff --git a/app/authentication/_layout.tsx b/app/authentication/_layout.tsx
index 4302423..b8325bc 100644
--- a/app/authentication/_layout.tsx
+++ b/app/authentication/_layout.tsx
@@ -17,6 +17,15 @@ const TabLayout: React.FC = () => {
         headerShown: false,
       }}
     >
+      <Tabs.Screen
+        name="about"
+        options={{
+          title: "About",
+          tabBarIcon: ({ color }) => {
+            return <TabBarIcon name="info" color={color} />
+          },
+        }}
+      />
       <Tabs.Screen
         name="login"
         options={{
diff --git a/app/authentication/about.tsx b/app/authentication/about.tsx
new file mode 100644
index 0000000..de3f25c
--- /dev/null
+++ b/app/authentication/about.tsx
@@ -0,0 +1,26 @@
+import { Button } from "react-native-paper"
+import { useRouter } from "expo-router"
+
+import { About } from "@/presentation/react-native/components/About"
+
+const AboutPage: React.FC = () => {
+  const router = useRouter()
+
+  return (
+    <About
+      actionButton={
+        <Button
+          mode="contained"
+          labelStyle={{ fontSize: 18 }}
+          onPress={() => {
+            router.push("/authentication/login")
+          }}
+        >
+          Get Started 🚀
+        </Button>
+      }
+    />
+  )
+}
+
+export default AboutPage
diff --git a/app/authentication/login.tsx b/app/authentication/login.tsx
index d6fea8c..944c828 100644
--- a/app/authentication/login.tsx
+++ b/app/authentication/login.tsx
@@ -67,6 +67,7 @@ const LoginPage: React.FC = () => {
 
       <Button
         mode="contained"
+        labelStyle={{ fontSize: 18 }}
         onPress={handleSubmit(onSubmit)}
         loading={login.state === "loading"}
         disabled={login.state === "loading"}
diff --git a/app/authentication/register.tsx b/app/authentication/register.tsx
index 74e8ceb..6664b07 100644
--- a/app/authentication/register.tsx
+++ b/app/authentication/register.tsx
@@ -107,6 +107,7 @@ const RegisterPage: React.FC = () => {
 
       <Button
         mode="contained"
+        labelStyle={{ fontSize: 18 }}
         onPress={handleSubmit(onSubmit)}
         loading={register.state === "loading"}
         disabled={register.state === "loading"}
diff --git a/app/index.tsx b/app/index.tsx
index c8c246b..275cb7c 100644
--- a/app/index.tsx
+++ b/app/index.tsx
@@ -6,7 +6,7 @@ const HomePage: React.FC = () => {
   const { user } = useAuthentication()
 
   if (user == null) {
-    return <Redirect href="/authentication/login" />
+    return <Redirect href="/authentication/about" />
   }
 
   return <Redirect href="/application/habits/" />
diff --git a/presentation/assets/images/Universite-Strasbourg.png b/presentation/assets/images/Universite-Strasbourg.png
deleted file mode 100644
index ff3bd48fb06081d82afb2f0e715652e2de907f27..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 10812
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

diff --git a/presentation/react-native/components/About.tsx b/presentation/react-native/components/About.tsx
new file mode 100644
index 0000000..62f523c
--- /dev/null
+++ b/presentation/react-native/components/About.tsx
@@ -0,0 +1,81 @@
+import { View } from "react-native"
+import { Text } from "react-native-paper"
+import { SafeAreaView } from "react-native-safe-area-context"
+
+import { ExternalLink } from "@/presentation/react-native/ui/ExternalLink"
+import { getVersion } from "@/utils/version"
+
+export interface AboutProps {
+  actionButton: React.ReactNode
+}
+
+export const About: React.FC<AboutProps> = (props) => {
+  const { actionButton } = props
+
+  const version = getVersion()
+
+  return (
+    <SafeAreaView
+      style={{
+        flex: 1,
+        paddingHorizontal: 20,
+      }}
+    >
+      <View style={{ alignItems: "center", marginVertical: 20 }}>
+        <Text
+          style={{
+            fontWeight: "bold",
+            fontSize: 28,
+            textAlign: "center",
+          }}
+        >
+          Habits Tracker
+        </Text>
+
+        <Text
+          style={{
+            marginTop: 6,
+            fontWeight: "bold",
+            fontSize: 18,
+            textAlign: "center",
+          }}
+        >
+          To perform at work and in everyday life.
+        </Text>
+
+        <Text
+          style={{
+            marginTop: 6,
+            fontWeight: "bold",
+            fontSize: 16,
+            textAlign: "center",
+          }}
+        >
+          v{version}
+        </Text>
+      </View>
+
+      <Text variant="bodyLarge" style={{ textAlign: "center" }}>
+        <ExternalLink href="https://unistra.fr" style={{ color: "#006CFF" }}>
+          Université de Strasbourg
+        </ExternalLink>
+      </Text>
+      <Text variant="bodyLarge" style={{ textAlign: "center" }}>
+        BUT Informatique - IUT Robert Schuman
+      </Text>
+      <Text variant="bodyLarge" style={{ textAlign: "center" }}>
+        P61 Mobile Development
+      </Text>
+
+      <View
+        style={{
+          justifyContent: "center",
+          alignItems: "center",
+          marginVertical: 20,
+        }}
+      >
+        {actionButton}
+      </View>
+    </SafeAreaView>
+  )
+}
diff --git a/utils/__tests__/version.test.ts b/utils/__tests__/version.test.ts
new file mode 100644
index 0000000..f9e94b0
--- /dev/null
+++ b/utils/__tests__/version.test.ts
@@ -0,0 +1,39 @@
+import { getVersion } from "../version"
+import { version } from "@/package.json"
+
+describe("utils/version", () => {
+  const env = process.env
+
+  beforeEach(() => {
+    jest.resetModules()
+    process.env = { ...env }
+  })
+
+  afterEach(() => {
+    process.env = env
+    jest.clearAllMocks()
+  })
+
+  it("should return '0.0.0-development' when NODE_ENV is 'development'", () => {
+    // Arrange - Given
+    process.env["NODE_ENV"] = "development"
+
+    // Act - When
+    const result = getVersion()
+
+    // Assert - Then
+    const expected = "0.0.0-development"
+    expect(result).toEqual(expected)
+  })
+
+  it("should return the version from package.json when NODE_ENV is not 'development'", () => {
+    // Arrange - Given
+    process.env["NODE_ENV"] = "production"
+
+    // Act - When
+    const result = getVersion()
+
+    // Assert - Then
+    expect(result).toEqual(version)
+  })
+})
diff --git a/utils/version.ts b/utils/version.ts
new file mode 100644
index 0000000..8ddaefb
--- /dev/null
+++ b/utils/version.ts
@@ -0,0 +1,8 @@
+import { version } from "@/package.json"
+
+export const getVersion = (): string => {
+  if (process.env["NODE_ENV"] === "development") {
+    return "0.0.0-development"
+  }
+  return version
+}
-- 
GitLab