diff --git a/README.md b/README.md
index ce3cc1b..bcd912a 100644
--- a/README.md
+++ b/README.md
@@ -59,11 +59,11 @@ Le projet de tp utilise un modèle de flux de travail Git pour organiser le dév
## Avancés du projet
* [x] Partie 0 - Project creation
* [x] Partie 1 - Project organisation
-* [ ] Partie 2 - Typescript types
-* [ ] Partie 3 - Screens
-* [ ] Partie 4 - Components
-* [ ] Partie 5 - FlatList
-* [ ] Partie 6 - Safe Area
+* [X] Partie 2 - Typescript types
+* [X] Partie 3 - Screens
+* [X] Partie 4 - Components
+* [X] Partie 5 - FlatList
+* [X] Partie 6 - Safe Area
* [ ] Partie 7 - Navigation
* [ ] Partie 8 - Hooks
* [ ] Partie 9 - Redux Store
diff --git a/src/tp-react-native/App.tsx b/src/tp-react-native/App.tsx
index 94b9564..f86f8c9 100644
--- a/src/tp-react-native/App.tsx
+++ b/src/tp-react-native/App.tsx
@@ -1,28 +1,7 @@
-import { StatusBar } from 'expo-status-bar';
-import { StyleSheet, Text, View } from 'react-native';
-import { customJokeStub } from './data/stub/CustomJokeStub';
-import { sampleJokeStub } from './data/stub/SampleJokeStub';
+import HomePage from './screens/HomeScreen';
-import './types/extension'
export default function App() {
return (
-
-
- CustomJoke
- {customJokeStub.displayDescription().map((t) =>{t})}
-
- SampleJoke
- {sampleJokeStub.displayDescription().map((t) =>{t})}
-
-
+
);
}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- backgroundColor: '#fff',
- alignItems: 'center',
- justifyContent: 'center',
- },
-});
diff --git a/src/tp-react-native/assets/Theme.ts b/src/tp-react-native/assets/Theme.ts
new file mode 100644
index 0000000..e1d6e48
--- /dev/null
+++ b/src/tp-react-native/assets/Theme.ts
@@ -0,0 +1,5 @@
+export const indigoColor = "rgba(14, 14, 44, 1)";
+export const purpleColor = "rgba(74, 74, 104, 1)";
+export const darksalmonColor = "rgba(233, 150, 122, 1)";
+export const greyColor = "rgba(140, 140, 161, 1)";
+export const whiteColor = "rgba(239, 239, 253, 1)";
\ No newline at end of file
diff --git a/src/tp-react-native/components/JokeListItem.tsx b/src/tp-react-native/components/JokeListItem.tsx
new file mode 100644
index 0000000..272c9f6
--- /dev/null
+++ b/src/tp-react-native/components/JokeListItem.tsx
@@ -0,0 +1,77 @@
+import {StyleSheet, Text, View, FlatList, Image} from 'react-native';
+import {SampleJoke} from "../model/SampleJoke";
+import {CustomJoke} from "../model/CustomJoke";
+import {darksalmonColor, whiteColor, greyColor, indigoColor} from "../assets/Theme";
+
+type JokeListItemProps = {
+ jokes: CustomJoke[] | SampleJoke[];
+};
+
+export default function JokeListItem(props: JokeListItemProps) {
+ const renderItem = ({ item }: { item: CustomJoke | SampleJoke }) => (
+
+
+
+
+ {item.id}
+ {item.description()}
+
+ {item.type}
+
+
+
+ );
+
+ return (
+ item.id.toString()}
+ renderItem={renderItem}
+ />
+ );
+}
+
+const styles = StyleSheet.create({
+ rowContainer: {
+ flexDirection: "row",
+ marginHorizontal: "5%",
+ marginBottom:7,
+ marginTop:7,
+ paddingVertical: 10,
+ backgroundColor: indigoColor,
+ width:'90%',
+ height:150,
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ },
+ color: {
+ flex: 0,
+ backgroundColor: darksalmonColor,
+ height: 150,
+ width:15,
+ },
+ image: {
+ width: '40%',
+ height: 150,
+ flex: 1
+ },
+ columnContainer: {
+ flexDirection: "column",
+ marginLeft: 20,
+ marginRight: 20,
+ width: '60%',
+ flex: 2,
+ justifyContent: 'space-between',
+ },
+ text: {
+ color:whiteColor,
+ paddingBottom: 7,
+ paddingTop: 7,
+ },
+ bottomContainer: {
+ backgroundColor: greyColor,
+ width:"auto",
+ height: 15,
+ borderRadius: 5
+ }
+});
\ No newline at end of file
diff --git a/src/tp-react-native/data/stub/CustomJokeStub.ts b/src/tp-react-native/data/stub/CustomJokeStub.ts
index d4d412f..1a60bc2 100644
--- a/src/tp-react-native/data/stub/CustomJokeStub.ts
+++ b/src/tp-react-native/data/stub/CustomJokeStub.ts
@@ -1,3 +1,13 @@
+/**
+ * @file CustomJokeStub.ts
+ * @brief Exemple d'utilisation de la classe JokeFactory pour créer des blagues personnalisées.
+ */
+
import { JokeFactory } from '../../model/JokeFactory';
-export const customJokeStub = JokeFactory.createCustomJokes('[{"id":"1", "type":"custom", "setup":"one", "punchline":"y\'en a pas", "image":"Jackson"},{"id":"2", "type":"custom", "setup":"two","punchline":"y\'en a pas", "image":"Jackson"}]');
\ No newline at end of file
+/**
+ * @brief Stub de blagues personnalisées créées à l'aide de la classe JokeFactory.
+ * @constant
+ * @type {CustomJoke[]}
+ */
+export const customJokeStub = JokeFactory.createCustomJokes('[{"id":"1", "type":"custom", "setup":"one", "punchline":"y\'en a pas", "image":"https://placekitten.com/200/300"},{"id":"2", "type":"custom", "setup":"two","punchline":"y\'en a pas", "image":"https://placekitten.com/200/300"},{"id":"3", "type":"Default", "setup":"three","punchline":"y\'en toujours a pas ;)", "image":"https://placekitten.com/200/300"},{"id":"4", "type":"custom bro", "setup":"four","punchline":"y\'en toujours toujours ap", "image":"https://placekitten.com/200/300"}]');
\ No newline at end of file
diff --git a/src/tp-react-native/data/stub/SampleJokeStub.ts b/src/tp-react-native/data/stub/SampleJokeStub.ts
index 390ed12..a9068ac 100644
--- a/src/tp-react-native/data/stub/SampleJokeStub.ts
+++ b/src/tp-react-native/data/stub/SampleJokeStub.ts
@@ -1,2 +1,13 @@
+/**
+ * @file SampleJokeStub.ts
+ * @brief Exemple d'utilisation de la classe JokeFactory pour créer des blagues simples.
+ */
+
import { JokeFactory } from '../../model/JokeFactory';
-export const sampleJokeStub = JokeFactory.createCustomJokes('[{"id":"1", "type":"custom", "setup":"one", "punchline":"y\'en a pas", "image":"Jackson"},{"id":"2", "type":"custom", "setup":"two","punchline":"y\'en a pas", "image":"Jackson"}]');
\ No newline at end of file
+
+/**
+ * @brief Stub de blagues simples créées à l'aide de la classe JokeFactory.
+ * @constant
+ * @type {SampleJoke[]}
+ */
+export const sampleJokeStub = JokeFactory.createSampleJokes('[{"id":1, "type":"custom", "setup":"one", "punchline":"y\'en a pas", "image":"https://placekitten.com/200/300"},{"id":2, "type":"custom", "setup":"two","punchline":"y\'en a pas", "image":"https://placekitten.com/200/300"}]');
\ No newline at end of file
diff --git a/src/tp-react-native/model/CustomJoke.ts b/src/tp-react-native/model/CustomJoke.ts
index f3f39a9..1561bec 100644
--- a/src/tp-react-native/model/CustomJoke.ts
+++ b/src/tp-react-native/model/CustomJoke.ts
@@ -1,18 +1,52 @@
+/**
+ * @file CustomJoke.ts
+ * @brief Définition de la classe CustomJoke.
+ */
+
import { Joke } from './Joke';
+/**
+ * @class
+ * @brief Représente une blague personnalisée avec un identifiant unique.
+ * @extends Joke
+ */
export class CustomJoke extends Joke {
- private _id:string;
+ private _id: string;
+
+ /**
+ * @brief Constructeur de la classe CustomJoke.
+ * @param {string} id - L'identifiant unique de la blague.
+ * @param {string} type - Le type de la blague.
+ * @param {string} setup - La partie préliminaire de la blague.
+ * @param {string} punchline - La chute de la blague.
+ * @param {string} image - L'URL de l'image associée à la blague.
+ */
constructor(id: string, type: string, setup: string, punchline: string, image: string) {
super(type, setup, punchline, image); // Assuming Joke class has these properties
this._id = id;
}
- public get id():string {
+
+ /**
+ * @brief Obtient l'identifiant de la blague.
+ * @return {string} L'identifiant de la blague.
+ */
+ get id(): string {
return this._id;
}
- public set id(id:string) {
+
+ /**
+ * @brief Modifie l'identifiant de la blague.
+ * @param {string} id - Le nouvel identifiant de la blague.
+ */
+ set id(id: string) {
this._id = id;
}
+
+ /**
+ * @brief Obtient une description textuelle de la blague.
+ * @return {string} La description de la blague.
+ */
description(): string {
return `ID: ${this.id}, Setup: ${this.setup}, Punchline: ${this.punchline}`;
}
-}
\ No newline at end of file
+}
diff --git a/src/tp-react-native/model/Joke.ts b/src/tp-react-native/model/Joke.ts
index 3684320..6ba180d 100644
--- a/src/tp-react-native/model/Joke.ts
+++ b/src/tp-react-native/model/Joke.ts
@@ -1,9 +1,25 @@
+/**
+ * @file Joke.ts
+ * @brief Définition de la classe abstraite Joke.
+ */
+
+/**
+ * @class
+ * @brief Classe abstraite représentant une blague.
+ */
export abstract class Joke {
private _type: string;
private _setup: string;
private _punchline: string;
private _image: string;
+ /**
+ * @brief Constructeur de la classe Joke.
+ * @param {string} type - Le type de la blague.
+ * @param {string} setup - La partie préliminaire de la blague.
+ * @param {string} punchline - La chute de la blague.
+ * @param {string} image - L'URL de l'image associée à la blague.
+ */
constructor(type: string, setup: string, punchline: string, image: string) {
this._type = type;
this._setup = setup;
@@ -11,33 +27,82 @@ export abstract class Joke {
this._image = image;
}
- public get type() {
+ /**
+ * @brief Obtient le type de la blague.
+ * @return {string} Le type de la blague.
+ */
+ get type() {
return this._type;
}
- public get setup():string {
+
+ /**
+ * @brief Obtient la partie préliminaire de la blague.
+ * @return {string} La partie préliminaire de la blague.
+ */
+ get setup(): string {
return this._setup;
}
- public get punchline():string {
+
+ /**
+ * @brief Obtient la chute de la blague.
+ * @return {string} La chute de la blague.
+ */
+ get punchline(): string {
return this._punchline;
}
- public get image():string {
+
+ /**
+ * @brief Obtient l'URL de l'image associée à la blague.
+ * @return {string} L'URL de l'image associée à la blague.
+ */
+ get image(): string {
return this._image;
}
- public set type(theType:string) {
+
+ /**
+ * @brief Modifie le type de la blague.
+ * @param {string} theType - Le nouveau type de la blague.
+ */
+ set type(theType: string) {
this._type = theType;
}
+
+ /**
+ * @brief Modifie la partie préliminaire de la blague.
+ * @param {string} theSetup - La nouvelle partie préliminaire de la blague.
+ */
public set setup(theSetup: string) {
this._setup = theSetup;
}
- public set punchline(thePunchline:string) {
+
+ /**
+ * @brief Modifie la chute de la blague.
+ * @param {string} thePunchline - La nouvelle chute de la blague.
+ */
+ public set punchline(thePunchline: string) {
this._punchline = thePunchline;
}
- public set image(theImage:string) {
+
+ /**
+ * @brief Modifie l'URL de l'image associée à la blague.
+ * @param {string} theImage - Le nouvel URL de l'image associée à la blague.
+ */
+ public set image(theImage: string) {
this._image = theImage;
}
+
+ /**
+ * @brief Obtient un résumé de la blague.
+ * @return {string} Un résumé de la blague.
+ */
public summary(): string {
- return this.punchline.substring(0,24) + "...";
+ return this.punchline.substring(0, 24) + "...";
}
+
+ /**
+ * @brief Obtient une description textuelle de la blague.
+ * @return {string} Une description textuelle de la blague.
+ */
public description(): string {
return this.type + this.summary;
}
diff --git a/src/tp-react-native/model/JokeFactory.ts b/src/tp-react-native/model/JokeFactory.ts
index 4102347..8267b7d 100644
--- a/src/tp-react-native/model/JokeFactory.ts
+++ b/src/tp-react-native/model/JokeFactory.ts
@@ -1,7 +1,21 @@
+/**
+ * @file JokeFactory.ts
+ * @brief Définition de la classe JokeFactory.
+ */
+
import { CustomJoke } from "./CustomJoke";
import { SampleJoke } from "./SampleJoke";
+/**
+ * @class
+ * @brief Fabrique de blagues permettant de créer des instances de blagues à partir de données JSON.
+ */
export class JokeFactory {
+ /**
+ * @brief Crée des instances de blagues personnalisées à partir d'un tableau JSON.
+ * @param {string} jsonArray - Tableau JSON représentant les blagues personnalisées.
+ * @return {CustomJoke[]} Tableau d'instances de blagues personnalisées.
+ */
public static createCustomJokes(jsonArray: string): CustomJoke[] {
const jsonObjects: any[] = JSON.parse(jsonArray);
const customJokes: CustomJoke[] = [];
@@ -20,6 +34,11 @@ export class JokeFactory {
return customJokes;
}
+ /**
+ * @brief Crée des instances de blagues d'échantillon à partir d'un tableau JSON.
+ * @param {string} jsonArray - Tableau JSON représentant les blagues d'échantillon.
+ * @return {SampleJoke[]} Tableau d'instances de blagues d'échantillon.
+ */
public static createSampleJokes(jsonArray: string): SampleJoke[] {
const jsonObjects: any[] = JSON.parse(jsonArray);
const sampleJokes: SampleJoke[] = [];
diff --git a/src/tp-react-native/model/SampleJoke.ts b/src/tp-react-native/model/SampleJoke.ts
index f9a108d..cb8e157 100644
--- a/src/tp-react-native/model/SampleJoke.ts
+++ b/src/tp-react-native/model/SampleJoke.ts
@@ -1,17 +1,51 @@
+/**
+ * @file SampleJoke.ts
+ * @brief Définition de la classe SampleJoke.
+ */
+
import { Joke } from "./Joke";
+/**
+ * @class
+ * @brief Classe représentant une blague d'échantillon.
+ * @extends Joke
+ */
export class SampleJoke extends Joke {
- private _id:number;
+ private _id: number;
+
+ /**
+ * @brief Constructeur de la classe SampleJoke.
+ * @param {number} id - L'identifiant de la blague d'échantillon.
+ * @param {string} type - Le type de la blague.
+ * @param {string} setup - La partie préliminaire de la blague.
+ * @param {string} punchline - La chute de la blague.
+ * @param {string} image - L'URL de l'image associée à la blague.
+ */
constructor(id: number, type: string, setup: string, punchline: string, image: string) {
super(type, setup, punchline, image); // Assuming Joke class has these properties
this._id = id;
}
- public get id():number {
+
+ /**
+ * @brief Obtient l'identifiant de la blague d'échantillon.
+ * @return {number} L'identifiant de la blague d'échantillon.
+ */
+ get id(): number {
return this._id;
}
- public set id(id:number) {
+
+ /**
+ * @brief Modifie l'identifiant de la blague d'échantillon.
+ * @param {number} id - Le nouvel identifiant de la blague d'échantillon.
+ */
+ set id(id: number) {
this._id = id;
}
+
+ /**
+ * @brief Obtient une description textuelle de la blague d'échantillon.
+ * @return {string} Une description textuelle de la blague d'échantillon.
+ */
description(): string {
return `ID: ${this.id}, Setup: ${this.setup}, Punchline: ${this.punchline}`;
}
diff --git a/src/tp-react-native/package-lock.json b/src/tp-react-native/package-lock.json
index 8478362..15f8124 100644
--- a/src/tp-react-native/package-lock.json
+++ b/src/tp-react-native/package-lock.json
@@ -8,11 +8,14 @@
"name": "tp-react-native",
"version": "1.0.0",
"dependencies": {
+ "@react-navigation/bottom-tabs": "^6.5.11",
+ "@react-navigation/native": "^6.1.9",
"@types/react": "~18.2.45",
"expo": "~50.0.3",
"expo-status-bar": "~1.11.1",
"react": "18.2.0",
"react-native": "0.73.2",
+ "react-native-gesture-handler": "^2.14.1",
"typescript": "^5.3.0"
},
"devDependencies": {
@@ -2008,6 +2011,17 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@egjs/hammerjs": {
+ "version": "2.0.17",
+ "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
+ "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==",
+ "dependencies": {
+ "@types/hammerjs": "^2.0.36"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/@expo/bunyan": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@expo/bunyan/-/bunyan-4.0.0.tgz",
@@ -5850,6 +5864,100 @@
"react-native": "*"
}
},
+ "node_modules/@react-navigation/bottom-tabs": {
+ "version": "6.5.11",
+ "resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.11.tgz",
+ "integrity": "sha512-CBN/NOdxnMvmjw+AJQI1kltOYaClTZmGec5pQ3ZNTPX86ytbIOylDIITKMfTgHZcIEFQDymx1SHeS++PIL3Szw==",
+ "dependencies": {
+ "@react-navigation/elements": "^1.3.21",
+ "color": "^4.2.3",
+ "warn-once": "^0.1.0"
+ },
+ "peerDependencies": {
+ "@react-navigation/native": "^6.0.0",
+ "react": "*",
+ "react-native": "*",
+ "react-native-safe-area-context": ">= 3.0.0",
+ "react-native-screens": ">= 3.0.0"
+ }
+ },
+ "node_modules/@react-navigation/core": {
+ "version": "6.4.10",
+ "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.10.tgz",
+ "integrity": "sha512-oYhqxETRHNHKsipm/BtGL0LI43Hs2VSFoWMbBdHK9OqgQPjTVUitslgLcPpo4zApCcmBWoOLX2qPxhsBda644A==",
+ "dependencies": {
+ "@react-navigation/routers": "^6.1.9",
+ "escape-string-regexp": "^4.0.0",
+ "nanoid": "^3.1.23",
+ "query-string": "^7.1.3",
+ "react-is": "^16.13.0",
+ "use-latest-callback": "^0.1.7"
+ },
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
+ "node_modules/@react-navigation/core/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@react-navigation/core/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/@react-navigation/elements": {
+ "version": "1.3.21",
+ "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.21.tgz",
+ "integrity": "sha512-eyS2C6McNR8ihUoYfc166O1D8VYVh9KIl0UQPI8/ZJVsStlfSTgeEEh+WXge6+7SFPnZ4ewzEJdSAHH+jzcEfg==",
+ "peerDependencies": {
+ "@react-navigation/native": "^6.0.0",
+ "react": "*",
+ "react-native": "*",
+ "react-native-safe-area-context": ">= 3.0.0"
+ }
+ },
+ "node_modules/@react-navigation/native": {
+ "version": "6.1.9",
+ "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.9.tgz",
+ "integrity": "sha512-AMuJDpwXE7UlfyhIXaUCCynXmv69Kb8NzKgKJO7v0k0L+u6xUTbt6xvshmJ79vsvaFyaEH9Jg5FMzek5/S5qNw==",
+ "dependencies": {
+ "@react-navigation/core": "^6.4.10",
+ "escape-string-regexp": "^4.0.0",
+ "fast-deep-equal": "^3.1.3",
+ "nanoid": "^3.1.23"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/@react-navigation/native/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@react-navigation/routers": {
+ "version": "6.1.9",
+ "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.9.tgz",
+ "integrity": "sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==",
+ "dependencies": {
+ "nanoid": "^3.1.23"
+ }
+ },
"node_modules/@segment/loosely-validate-event": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz",
@@ -5898,6 +6006,11 @@
"@sinonjs/commons": "^3.0.0"
}
},
+ "node_modules/@types/hammerjs": {
+ "version": "2.0.45",
+ "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.45.tgz",
+ "integrity": "sha512-qkcUlZmX6c4J8q45taBKTL3p+LbITgyx7qhlPYOdOHZB7B31K0mXbP5YA7i7SgDeEGuI9MnumiKPEMrxg8j3KQ=="
+ },
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
@@ -6866,6 +6979,18 @@
"node": ">=6"
}
},
+ "node_modules/color": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=12.5.0"
+ }
+ },
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -6879,6 +7004,31 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
},
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "node_modules/color/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
"node_modules/colorette": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
@@ -7116,6 +7266,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/decode-uri-component": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
+ "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
@@ -7651,6 +7809,11 @@
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-1.11.1.tgz",
"integrity": "sha512-ddQEtCOgYHTLlFUe/yH67dDBIoct5VIULthyT3LRJbEwdpzAgueKsX2FYK02ldh440V87PWKCamh7R9evk1rrg=="
},
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
"node_modules/fast-glob": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
@@ -7746,6 +7909,14 @@
"node": ">=8"
}
},
+ "node_modules/filter-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
+ "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/finalhandler": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
@@ -8079,6 +8250,19 @@
"node": ">=8"
}
},
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hoist-non-react-statics/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
"node_modules/hosted-git-info": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz",
@@ -11110,6 +11294,23 @@
"qrcode-terminal": "bin/qrcode-terminal.js"
}
},
+ "node_modules/query-string": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
+ "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==",
+ "dependencies": {
+ "decode-uri-component": "^0.2.2",
+ "filter-obj": "^1.1.0",
+ "split-on-first": "^1.0.0",
+ "strict-uri-encode": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/queue": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
@@ -11199,6 +11400,18 @@
}
}
},
+ "node_modules/react-freeze": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.3.tgz",
+ "integrity": "sha512-ZnXwLQnGzrDpHBHiC56TXFXvmolPeMjTn1UOm610M4EXGzbEDR7oOIyS2ZiItgbs6eZc4oU/a0hpk8PrcKvv5g==",
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": ">=17.0.0"
+ }
+ },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -11257,6 +11470,46 @@
"react": "18.2.0"
}
},
+ "node_modules/react-native-gesture-handler": {
+ "version": "2.14.1",
+ "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.14.1.tgz",
+ "integrity": "sha512-YiM1BApV4aKeuwsM6O4C2ufwewYEKk6VMXOt0YqEZFMwABBFWhXLySFZYjBSNRU2USGppJbfHP1q1DfFQpKhdA==",
+ "dependencies": {
+ "@egjs/hammerjs": "^2.0.17",
+ "hoist-non-react-statics": "^3.3.0",
+ "invariant": "^2.2.4",
+ "lodash": "^4.17.21",
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/react-native-safe-area-context": {
+ "version": "4.8.2",
+ "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.8.2.tgz",
+ "integrity": "sha512-ffUOv8BJQ6RqO3nLml5gxJ6ab3EestPiyWekxdzO/1MQ7NF8fW1Mzh1C5QE9yq573Xefnc7FuzGXjtesZGv7cQ==",
+ "peer": true,
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/react-native-screens": {
+ "version": "3.29.0",
+ "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.29.0.tgz",
+ "integrity": "sha512-yB1GoAMamFAcYf4ku94uBPn0/ani9QG7NdI98beJ5cet2YFESYYzuEIuU+kt+CNRcO8qqKeugxlfgAa3HyTqlg==",
+ "peer": true,
+ "dependencies": {
+ "react-freeze": "^1.0.0",
+ "warn-once": "^0.1.0"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/react-native/node_modules/promise": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
@@ -11740,6 +11993,19 @@
"node": ">= 5.10.0"
}
},
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/simple-swizzle/node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+ },
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@@ -11818,6 +12084,14 @@
"node": "*"
}
},
+ "node_modules/split-on-first": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
+ "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@@ -11893,6 +12167,14 @@
"node": ">= 0.10.0"
}
},
+ "node_modules/strict-uri-encode": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
+ "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -12522,6 +12804,14 @@
"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz",
"integrity": "sha512-EGXjXJZhIHiQMK2pQukuFcL303nskqIRzWvPvV5O8miOfwoUb9G+a/Cld60kUyeaybEI94wvVClT10DtfeAExA=="
},
+ "node_modules/use-latest-callback": {
+ "version": "0.1.9",
+ "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.9.tgz",
+ "integrity": "sha512-CL/29uS74AwreI/f2oz2hLTW7ZqVeV5+gxFeGudzQrgkCytrHw33G4KbnQOrRlAEzzAFXi7dDLMC9zhWcVpzmw==",
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -12577,6 +12867,11 @@
"makeerror": "1.0.12"
}
},
+ "node_modules/warn-once": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz",
+ "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q=="
+ },
"node_modules/wcwidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
diff --git a/src/tp-react-native/package.json b/src/tp-react-native/package.json
index b26d8d7..96d175d 100644
--- a/src/tp-react-native/package.json
+++ b/src/tp-react-native/package.json
@@ -10,12 +10,15 @@
"web": "expo start --web"
},
"dependencies": {
+ "@react-navigation/bottom-tabs": "^6.5.11",
+ "@react-navigation/native": "^6.1.9",
+ "@types/react": "~18.2.45",
"expo": "~50.0.3",
"expo-status-bar": "~1.11.1",
"react": "18.2.0",
"react-native": "0.73.2",
- "typescript": "^5.3.0",
- "@types/react": "~18.2.45"
+ "react-native-gesture-handler": "^2.14.1",
+ "typescript": "^5.3.0"
},
"devDependencies": {
"@babel/core": "^7.20.0"
diff --git a/src/tp-react-native/screens/HomeScreen.tsx b/src/tp-react-native/screens/HomeScreen.tsx
new file mode 100644
index 0000000..eb4e7e1
--- /dev/null
+++ b/src/tp-react-native/screens/HomeScreen.tsx
@@ -0,0 +1,44 @@
+import { StatusBar } from 'expo-status-bar';
+import { StyleSheet, Text, View } from 'react-native';
+import { customJokeStub } from '../data/stub/CustomJokeStub';
+import { sampleJokeStub } from '../data/stub/SampleJokeStub';
+import { SafeAreaView } from 'react-native'
+import JokeListItem from "../components/JokeListItem";
+import '../types/extension';
+import {darksalmonColor, indigoColor, purpleColor} from "../assets/Theme";
+
+export default function HomeScreen() {
+ const allJokes = [...customJokeStub, ...sampleJokeStub];
+return (
+ <>
+
+
+
+ Catalogue
+
+
+
+
+ >
+)
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: purpleColor,
+ },
+ centered: {
+ color:darksalmonColor,
+ fontSize:24,
+ textAlign: "center",
+ paddingBottom:20,
+ },
+ title: {
+ backgroundColor: indigoColor
+ },
+ topSafeArea: {
+ flex: 0,
+ backgroundColor: indigoColor
+ }
+});
\ No newline at end of file