Développement d'applications mobiles

L'application Recipeasy sera développée de façon itérative au fil de notre apprentissage de React Native.

  • Créez un répertoire pour le projet sur Bitbucket et me le partager via l'adresse jhoffman@cshawi.ca
    • Le code de l'application doit se trouver à la racine du répertoire
  • Vous utiliserez également une branche distincte identifiant chacune des remises itérative. Seul le code sur la branche précisée sera considéré pour la correction.
  • Chaque itération devrait être constituée de plusieurs commits, représentant une unité fonctionnelle dans la réalisation de l'itération en cours

1- Interface utilisateur

Remise 06/09/2024 @ 8h AM

Les prototypes d'écrans représentent une maquette, donc vous pouvez utiliser des couleurs différentes ou une librairie de composants différente sans changer la mise en forme significativement

  • Exploitez judicieusement la séparation en components et l'organisation des fichiers
  • Assurez-vous d'implémenter les Safe Areas, pour éviter de masquer le contenu

Pour cette première itération, implémentez seulement le contenu statique des écrans suivants:

Librairies suggérées

Boutons radio 📚 RN Radio Buttons Group
bash
npx expo install react-native-radio-buttons-group
import { View } from 'react-native';

import RadioGroup from 'react-native-radio-buttons-group';

export default function App() {

const options = [
{
id: '1',
label: 'One',
value: '1'
},
{
id: '2',
label: 'Two',
value: '2'
}
];

return (
<View>
<RadioGroup radioButtons={ options } />
</View>
);
}

Liste déroulante 📚 Expo Picker
bash
npx expo install @react-native-picker/picker
import { View } from 'react-native';
import { Picker } from '@react-native-picker/picker';

export default function App() {

return (
<View>

<Picker>
<Picker.Item label="One" value="1" />
<Picker.Item label="Two" value="2" />
</Picker>

</View>
);

}

Développement d'applications mobiles

Nom:

Bitbucket, Branche remise-ui 1     0
Écrans
Connexion 2     1.5     1     0
Inscription 2     1.5     1     0
Formulaire de recette 3     2.5     2     1     0
Appréciation générale
UI 0     -0.5     -1
Code 0     -0.5     -1

2- Interactions

Remise 20/09/2024 @ 8h AM

À partir des écrans créé précédemment, ajouter la navigation en respectant le storyboard

  • Assurez-vous de respecter votre thème de couleur

Comportement minimal

Liste des recettes

Pour nous permettre de continuer le développement, nous créons un écran provisoire pour afficher la liste des recettes. À court-terme, cet écran est responsable de stocker la liste des recettes et d'offrir des interactions de base.

  • Bouton View ouvre le détail d'une recette aléatoire de la liste
  • Bouton Add ouvre le détail en mode ajout
  • Un texte affiche le tableau de recettes brutes en string, JSON.stringify(...)
    • Triée par nom, en ordre croissant

  • On ajoute un bouton Log out dans la barre de navigation qui retourne au login
  • L'option back de la barre de navigation est désactivée

Formulaire d'une recette

Permet d'ajouter une nouvelle recette ou de consulter en édition une recette existante reçue en paramètre de navigation.

  • Pour la création, les données doivent être valides
    • Catégorie requise
    • Nom requis, non vide
    • Durée > 0

  • Le bouton Delete est disponible en édition uniquement et retourne simplement à la liste

    • PAS de suppression à implémenter

  • Le bouton Save est disponible en ajout uniquement et retourne la nouvelle recette à la liste

    • La liste se mets à jour
    • PAS d'édition à implémenter

js
Structure d'une recette
{
category: Number,
name: String,
durationHours: Number,
durationMinutes: Number,
description: String
}

Librairie suggérée

React Native Toast Miguel

Développement d'applications mobiles

Nom:

Branche remise-ux, commits 1     0.5     0
Navigation
Login, Signup 1     0.5     0
Log out, back caché 1     0.5     0
Liste, Ajout/Édition 1     0.5     0
Comportement
Liste brute, trié par nom ascendant, se mets à jour 1     0.5     0
Ajout, validations 1     0.5     0
Édition, recette aléatoire, données cohérentes 1     0.5     0
Boutons Save, Delete 1     0.5     0
Appréciation générale
UI 0     -0.5     -1
UX 0     -0.5     -1
Code 0     -0.5     -1

Liste

Ajouter l'affichage des recettes en utilisant un mécanisme de liste optimal en considérant les aspects suivants:

  • Affichage d'un message si la liste est vide
  • Affichage d'un séparateur
  • Chaque item de la liste affiche
    • une icône pour la catégorie
    • la durée formatée en heures-minutes XhYY
    • le nom
    • la description
  • Item cliquable, avec une rétroaction visuelle, qui amène au détail correspondant
  • Mise à jour de la liste lors d'un ajout

Penser également à créer manuellement des recettes de départ, seeds, pour tester votre affichage.

Vide
Liste
Clic

Authentification

Intégrer les modèles et services fournis pour permettre l'authentification des utilisateurs.

  • Pour l'instant, il n'est pas nécessaire d'associer des recettes à chaque utilisateur, ce sera fait lors de la communication avec le serveur de base de données.

3- HTTP

Implémenter les fonctionnalités d'authentification et CRUDL des recettes via l'API HTTP Martha à partir des fichiers fournis.

  • Mettre à jour l'écran Recipe pour afficher un bouton Save en édition
  • Exploiter judicieusement les services et les models pour traiter les données
  • Ajouter la gestion d'erreurs dans la communication HTTP

Recipeasy ✖️ Martha

⬇️ Fichiers Martha

export class User {

#id;

constructor({ id, username }) {
this.#id = id
this.username = username


get id()
return this.#id
}

toJSON() {
return {
id: this.#id,
...this
}
}

}

import { User } from '../models/User.js'

class AuthService {
// ...

async signUp(credentials) {
const response = await fetch("http://martha.jh.shawinigan.info/queries/insert-user/execute", {
method: 'POST',
body: JSON.stringify(credentials),
headers: {
'auth': 'YTphbGxvbDNTVVBFUk1PTkRFIQ=='
}
}).then((r) => r.json())

if (response.success) {
this.#currentUser = new User({ id: response.lastInsertId, username: credentials.username })
}

return !!this.#currentUser
}

async logIn(credentials) {
const response = await fetch("http://martha.jh.shawinigan.info/queries/select-user-auth/execute", {
method: 'POST',
body: JSON.stringify(credentials),
headers: {
'auth': 'YTphbGxvbDNTVVBFUk1PTkRFIQ=='
}
}).then((r) => r.json())

if (response.success && response.data.length == 1) {
const user = response.data[0]
this.#currentUser = new User({ id: user.id, username: user.username })
console.log(JSON.stringify(this.#currentUser))
} else
this.#currentUser = null
}

return !!this.#currentUser
}

// ...
}

const service = new AuthService();
export default service;

Développement d'applications mobiles

HTTP - 5%

/ 17

Nom:

Branche remise-data, commits 1     0.5     0
Liste
Mécanisme optimal 1     0
Liste vide 1     0.5     0
Item: icône, durée formatée, nom, description 2     1.5     1     0
Séparateur 1     0.5     0
Item clic, rétroaction, navigue vers le détail correspondant 2     1.5     1     0
CRUDL HTTP
Authentification via Martha 0     -1
C R U D L des recettes via Martha 4     3.5     3     2     1     0
Gestion des erreurs 2     1.5     1     0
Séparation judicieuse des responsabilités 3     2.5     2     1     0
Appréciation générale
UI 0     -0.5     -1
UX 0     -0.5     -1
Code 0     -0.5     -1

Refactoring

Pour favoriser l'intégration des rétroactions lors des remises itératives, vous avez l'opportunité de récupérer 50% des points perdus lors du laboratoire en implémentant les correctifs associés aux commentaires reçus.

Complétez les changements au plus tard lundi 21 octobre 8h AM, votre répertoire sera récupéré et vous devrez me les démontrer individuellement pour valider votre ajustement de note.