From d945eb772b3d39dbc4b8c29457a379166ff91a92 Mon Sep 17 00:00:00 2001 From: dj222837 Date: Wed, 22 Oct 2025 10:55:39 +0200 Subject: [PATCH] Initial commit --- README.md | 73 + client/.gitignore | 41 + client/App.tsx | 16 + client/CheckoutScreen.tsx | 97 + client/app.json | 40 + client/assets/adaptive-icon.png | Bin 0 -> 17547 bytes client/assets/favicon.png | Bin 0 -> 1466 bytes client/assets/icon.png | Bin 0 -> 22380 bytes client/assets/splash-icon.png | Bin 0 -> 17547 bytes client/index.ts | 8 + client/package-lock.json | 9428 ++++++++++++++++++++++ client/package.json | 24 + client/tsconfig.json | 7 + server/.gitignore | 162 + server/Dockerfile | 23 + server/README.md | 83 + server/docker-compose.yml | 11 + server/poetry.lock | 765 ++ server/pyproject.toml | 22 + server/src/core/__init__.py | 48 + server/src/core/customers/__init__.py | 1 + server/src/core/customers/controllers.py | 40 + server/src/core/customers/models.py | 15 + server/src/core/customers/routes.py | 36 + server/src/core/customers/schemas.py | 18 + server/src/core/database.py | 18 + server/src/core/exceptions.py | 34 + server/src/core/items/__init__.py | 1 + server/src/core/items/controllers.py | 53 + server/src/core/items/models.py | 31 + server/src/core/items/routes.py | 44 + server/src/core/items/schemas.py | 45 + server/src/core/payments/__init__.py | 1 + server/src/core/payments/controllers.py | 16 + server/src/core/payments/models.py | 19 + server/src/core/payments/routes.py | 165 + server/src/core/payments/schemas.py | 43 + server/src/main.py | 4 + 38 files changed, 11432 insertions(+) create mode 100644 README.md create mode 100644 client/.gitignore create mode 100644 client/App.tsx create mode 100644 client/CheckoutScreen.tsx create mode 100644 client/app.json create mode 100644 client/assets/adaptive-icon.png create mode 100644 client/assets/favicon.png create mode 100644 client/assets/icon.png create mode 100644 client/assets/splash-icon.png create mode 100644 client/index.ts create mode 100644 client/package-lock.json create mode 100644 client/package.json create mode 100644 client/tsconfig.json create mode 100644 server/.gitignore create mode 100644 server/Dockerfile create mode 100644 server/README.md create mode 100644 server/docker-compose.yml create mode 100644 server/poetry.lock create mode 100644 server/pyproject.toml create mode 100644 server/src/core/__init__.py create mode 100644 server/src/core/customers/__init__.py create mode 100644 server/src/core/customers/controllers.py create mode 100644 server/src/core/customers/models.py create mode 100644 server/src/core/customers/routes.py create mode 100644 server/src/core/customers/schemas.py create mode 100644 server/src/core/database.py create mode 100644 server/src/core/exceptions.py create mode 100644 server/src/core/items/__init__.py create mode 100644 server/src/core/items/controllers.py create mode 100644 server/src/core/items/models.py create mode 100644 server/src/core/items/routes.py create mode 100644 server/src/core/items/schemas.py create mode 100644 server/src/core/payments/__init__.py create mode 100644 server/src/core/payments/controllers.py create mode 100644 server/src/core/payments/models.py create mode 100644 server/src/core/payments/routes.py create mode 100644 server/src/core/payments/schemas.py create mode 100644 server/src/main.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..5a8f771 --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +# Barcode Scanner + +| Nom | Prénom | +|---------|--------| +| Doe | Jane | +| Doe | John | + +Le TP est à réaliser par groupe de 2. + +## Compétences évaluées + +| Compétence | Aptitude | Description | Acquis | Remarque | +|------------|----------|----------------------------------------------------------------------------------------------------|--------|----------| +| D1 | C2 | Maîtriser la gestion des variables d’environnement d’une application | | | +| D2 | C1 | Maîtriser la création d’interfaces graphiques à l’aide de React Native | | | +| | C1 | Maîtriser l’API Stripe Javascript | | | +| | C3 | Maîtriser l’architecture logicielle d’un projet (services, composants, types, interfaces, classes) | | | +| | C3 | Maîtriser l’écriture de code asynchrone | | | +| | C3 | Savoir rédiger une documentaion | | | +| D4 | C1 | Maîtriser git | | | +| | C4 | Savoir respecter l’énoncé et l’échéance | | | + +## Technologies requises + +Vous allez avoir besoin des technologies suivantes : +- [Android Studio](https://developer.android.com/studio "Android Studio") +- [Docker](https://www.docker.com "Docker") Desktop ou CLI +- [NodeJS LTS](https://nodejs.org/fr "NodeJS") +- Un compte [Stripe](https://stripe.com/fr "Stripe") + +## Travail à réaliser + +Vous devez réaliser une application d'achat d'objets en tout genre à l'aide de Stripe. + +Elle doit comprendre les pages/fonctionnalités suivantes : + +- Scan de codes-barres : + - Accès au panier ; + - Si l'appareil photo n'est pas disponible, il faut pouvoir ajouter les articles manuellement ; + - Une vérification via l'API est nécessaire afin de savoir si l'article existe. +- Un panier : + - Contient l'ensemble des articles scannés ; + - Accessible depuis la page de scan des articles ; + - Possibilité de retirer du panier un article scanné ; + - Lorsque qu'un article est ajouté plusieurs fois, afficher un indicateur précisant le nombre du même article ; + - Possibilité d'augmenter la quantité d'un article déjà scanné ; + - Possibilité de payer les articles sélectionnés à l'aide de Stripe ; + - Sauvergarde du panier pour de futurs achats. +- Un historique des articles payés. +- Un [thème jour/nuit](https://m2.material.io/design/color/dark-theme.html#ui-application). + + +Le projet est composé des choses suivantes : +- [Server](./server/README.md) : Une API développée avec FastAPI afin d'utiliser Stripe. Vous pouvez implémenter la votre. +- [Client](./client/README.md) : Une application React Native de départ, c'est ici que vous allez développer l'application. + +Il est imposé d'utiliser `Expo.SQLite` pour la persistence des données au niveau du client. + +***Il est important de configurer le serveur avant le client.*** + +## Informations + +Le projet a été créé l'aide de la commande suivante : + +```shell +npx create-expo-app -t expo-template-blank-typescript +``` + +Il est possible de lancer l'application dans un émulateur Android et/ou iOS : + +```shell +npx expo run:android # npx expo run:ios +``` diff --git a/client/.gitignore b/client/.gitignore new file mode 100644 index 0000000..d914c32 --- /dev/null +++ b/client/.gitignore @@ -0,0 +1,41 @@ +# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files + +# dependencies +node_modules/ + +# Expo +.expo/ +dist/ +web-build/ +expo-env.d.ts + +# Native +.kotlin/ +*.orig.* +*.jks +*.p8 +*.p12 +*.key +*.mobileprovision + +# Metro +.metro-health-check* + +# debug +npm-debug.* +yarn-debug.* +yarn-error.* + +# macOS +.DS_Store +*.pem + +# local env files +.env*.local + +# typescript +*.tsbuildinfo + +# generated native folders +/ios +/android diff --git a/client/App.tsx b/client/App.tsx new file mode 100644 index 0000000..7b427b7 --- /dev/null +++ b/client/App.tsx @@ -0,0 +1,16 @@ +import { StripeProvider } from '@stripe/stripe-react-native'; +import CheckoutScreen from './CheckoutScreen'; +import React from 'react'; + +export default function App() { + const stripePK = "pk_test_51SKwERQq66qTCnSLfpU75kBYasSolAbCKhA64jLG3r3q3XX4cCuJtv5M69juxlLE4Ptz0yp1fo8tSbxGFVMPecBv00AubYeo2l" + + return ( + + + + ); +} diff --git a/client/CheckoutScreen.tsx b/client/CheckoutScreen.tsx new file mode 100644 index 0000000..b7a3ec7 --- /dev/null +++ b/client/CheckoutScreen.tsx @@ -0,0 +1,97 @@ +import { useStripe } from "@stripe/stripe-react-native"; +import React, { useEffect, useState } from "react"; +import { Alert, Text, Button, SafeAreaView } from "react-native"; + +export default function CheckoutScreen() { + const { initPaymentSheet, presentPaymentSheet } = useStripe(); + const [loading, setLoading] = useState(false); + const [paymentIntentId, setPaymentIntentId] = useState(""); + + const apiUrl = "http://172.26.7.103:8000"; + + const userId = "cus_THVVhujjj328BN"; + const items = [ + { + "id": 1, + "amount": 2 + } + ]; + + const fetchPaymentSheetParams = async () => { + const response = await fetch(`${apiUrl}/payments/`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + "pending_items": items, + "customer_id": userId + }) + }); + + const { paymentIntent, ephemeralKey, customer } = await response.json(); + + return { + paymentIntent, + ephemeralKey, + customer, + }; + }; + + const initializePaymentSheet = async () => { + const { + paymentIntent, + ephemeralKey, + customer, + } = await fetchPaymentSheetParams(); + + const { error } = await initPaymentSheet({ + merchantDisplayName: "Example, Inc.", + customerId: customer, + customerEphemeralKeySecret: ephemeralKey, + paymentIntentClientSecret: paymentIntent, + allowsDelayedPaymentMethods: false, + }); + + if (!error) { + setPaymentIntentId(paymentIntent); + setLoading(true); + } + }; + + const openPaymentSheet = async () => { + const { error } = await presentPaymentSheet(); + + if (error) { + Alert.alert(`Error code: ${error.code}`, error.message); + } else { + const paymentIntent = `pi_${paymentIntentId.split("_")[1]}`; + const response = await fetch(`${apiUrl}/payments/check/${paymentIntent}`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + "customer_id": userId + }) + }); + + if (response.status == 200) Alert.alert('Success', 'Your order is confirmed!'); + } + }; + + useEffect(() => { + initializePaymentSheet(); + }, []); + + return ( + + Payment +