mirror of
https://github.com/theoludwig/p61-project.git
synced 2024-07-17 07:00:12 +02:00
Merge branch 'develop' into feat/icon-picker
This commit is contained in:
commit
cf959c7088
@ -28,9 +28,6 @@ Un tracker d'habitudes pour performer au boulot et dans la vie de tous les jours
|
||||
- [React Native Paper](https://callstack.github.io/react-native-paper/): Bibliothèque de composants pour React Native.
|
||||
- [React Hook Form](https://react-hook-form.com/) + [Zod](https://zod.dev/): Gestion des formulaires et validation des données.
|
||||
- [Supabase](https://supabase.io/): Backend, serveur d'API pour le stockage des données.
|
||||
<!--
|
||||
- [WatermelonDB](https://nozbe.github.io/WatermelonDB/): Base de données locale, pour permettre une utilisation hors-ligne de l'application.
|
||||
-->
|
||||
|
||||
## Développement du projet en local
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Redirect, useLocalSearchParams } from "expo-router"
|
||||
import { Text } from "react-native-paper"
|
||||
import { SafeAreaView } from "react-native-safe-area-context"
|
||||
|
||||
import { HabitEditForm } from "@/presentation/react/components/HabitEditForm/HabitEditForm"
|
||||
import { useHabitsTracker } from "@/presentation/react/contexts/HabitsTracker"
|
||||
|
||||
const HabitPage: React.FC = () => {
|
||||
@ -9,23 +8,13 @@ const HabitPage: React.FC = () => {
|
||||
const { habitsTracker } = useHabitsTracker()
|
||||
|
||||
const habitHistory = habitsTracker.getHabitHistoryById(habitId as string)
|
||||
|
||||
if (habitHistory == null) {
|
||||
return <Redirect href="/application/habits/" />
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
style={[
|
||||
{
|
||||
flex: 1,
|
||||
alignItems: "center",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Text>
|
||||
Habit Page {habitId} {habitHistory.habit.name}
|
||||
</Text>
|
||||
</SafeAreaView>
|
||||
<HabitEditForm habit={habitHistory.habit} key={habitHistory.habit.id} />
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { useAuthentication } from "@/presentation/react/contexts/Authentication"
|
||||
const NewHabitPage: React.FC = () => {
|
||||
const { user } = useAuthentication()
|
||||
|
||||
if (user === null) {
|
||||
if (user == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,6 @@
|
||||
|
||||
Le **Modèle Logique des Données (MLD)** est une représentation de la structure de la base de données de l'application.
|
||||
|
||||
On représente ainsi les données sous la forme suivante:
|
||||
|
||||
- Chaque table est représentée par un bloc.
|
||||
- Le nom de la table est écrit en **gras**.
|
||||
- Les champs sont listés en dessous du nom de la table.
|
||||
- Les clés primaires sont <u>soulignées</u> et placées au début de la liste des champs.
|
||||
- Les clés étrangères sont préfixées par un dièse (#), et placées après les clés primaires. Les clés étrangères sont suivies entre parenthèses du nom de la table suivi d'une flèche (->) et du nom du champ de la table référencée.
|
||||
|
||||
## Modèle
|
||||
|
||||
- **users**
|
||||
|
@ -15,6 +15,9 @@ export const HabitCreateSchema = HabitSchema.extend({
|
||||
}).omit({ id: true })
|
||||
export type HabitCreateData = z.infer<typeof HabitCreateSchema>
|
||||
|
||||
export const HabitEditSchema = HabitSchema.extend({})
|
||||
export type HabitEditData = z.infer<typeof HabitEditSchema>
|
||||
|
||||
type HabitBase = z.infer<typeof HabitSchema>
|
||||
|
||||
export interface HabitData extends HabitBase {
|
||||
|
@ -34,7 +34,7 @@ export class HabitHistory implements HabitHistoryJSON {
|
||||
})
|
||||
}
|
||||
|
||||
private getProgressesByDate(date: Date): HabitProgress[] {
|
||||
public getProgressesByDate(date: Date): HabitProgress[] {
|
||||
return this._progressHistory.filter((progress) => {
|
||||
if (this.habit.goal.frequency === "monthly") {
|
||||
return (
|
||||
|
@ -1,6 +1,7 @@
|
||||
import type { GoalFrequency } from "./Goal"
|
||||
import type { Habit } from "./Habit"
|
||||
import { HabitHistory } from "./HabitHistory"
|
||||
import type { HabitProgress } from "./HabitProgress"
|
||||
|
||||
export interface HabitsTrackerData {
|
||||
habitsHistory: {
|
||||
@ -35,6 +36,33 @@ export class HabitsTracker implements HabitsTrackerData {
|
||||
)
|
||||
}
|
||||
|
||||
public editHabit(habit: Habit): void {
|
||||
const habitHistory = this.getHabitHistoryById(habit.id)
|
||||
if (habitHistory == null) {
|
||||
return
|
||||
}
|
||||
habitHistory.habit = habit
|
||||
}
|
||||
|
||||
public updateHabitProgress(habitProgress: HabitProgress): void {
|
||||
const habitHistory = this.getHabitHistoryById(habitProgress.habitId)
|
||||
if (habitHistory == null) {
|
||||
return
|
||||
}
|
||||
const habitProgressSaved = habitHistory.progressHistory.find((progress) => {
|
||||
return progress.id === habitProgress.id
|
||||
})
|
||||
if (habitProgressSaved == null) {
|
||||
habitHistory.progressHistory = [
|
||||
...habitHistory.progressHistory,
|
||||
habitProgress,
|
||||
]
|
||||
return
|
||||
}
|
||||
habitProgressSaved.goalProgress = habitProgress.goalProgress
|
||||
habitProgressSaved.date = habitProgress.date
|
||||
}
|
||||
|
||||
public getAllHabitsHistory(): HabitHistory[] {
|
||||
return [
|
||||
...this.habitsHistory.daily,
|
||||
|
9
domain/repositories/HabitEdit.ts
Normal file
9
domain/repositories/HabitEdit.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import type { Habit, HabitEditData } from "../entities/Habit"
|
||||
|
||||
export interface HabitEditOptions {
|
||||
habitEditData: HabitEditData
|
||||
}
|
||||
|
||||
export interface HabitEditRepository {
|
||||
execute: (options: HabitEditOptions) => Promise<Habit>
|
||||
}
|
12
domain/repositories/HabitProgressCreate.ts
Normal file
12
domain/repositories/HabitProgressCreate.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import type {
|
||||
HabitProgress,
|
||||
HabitProgressData,
|
||||
} from "../entities/HabitProgress"
|
||||
|
||||
export interface HabitProgressCreateOptions {
|
||||
habitProgressData: Omit<HabitProgressData, "id">
|
||||
}
|
||||
|
||||
export interface HabitProgressCreateRepository {
|
||||
execute: (options: HabitProgressCreateOptions) => Promise<HabitProgress>
|
||||
}
|
12
domain/repositories/HabitProgressUpdate.ts
Normal file
12
domain/repositories/HabitProgressUpdate.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import type {
|
||||
HabitProgress,
|
||||
HabitProgressData,
|
||||
} from "../entities/HabitProgress"
|
||||
|
||||
export interface HabitProgressUpdateOptions {
|
||||
habitProgressData: Omit<HabitProgressData, "habitId">
|
||||
}
|
||||
|
||||
export interface HabitProgressUpdateRepository {
|
||||
execute: (options: HabitProgressUpdateOptions) => Promise<HabitProgress>
|
||||
}
|
23
domain/use-cases/HabitEdit.ts
Normal file
23
domain/use-cases/HabitEdit.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import type { Habit } from "../entities/Habit"
|
||||
import { HabitEditSchema } from "../entities/Habit"
|
||||
import type { HabitEditRepository } from "../repositories/HabitEdit"
|
||||
|
||||
export interface HabitEditUseCaseDependencyOptions {
|
||||
habitEditRepository: HabitEditRepository
|
||||
}
|
||||
|
||||
export class HabitEditUseCase implements HabitEditUseCaseDependencyOptions {
|
||||
public habitEditRepository: HabitEditRepository
|
||||
|
||||
public constructor(options: HabitEditUseCaseDependencyOptions) {
|
||||
this.habitEditRepository = options.habitEditRepository
|
||||
}
|
||||
|
||||
public async execute(data: unknown): Promise<Habit> {
|
||||
const habitEditData = await HabitEditSchema.parseAsync(data)
|
||||
const habit = await this.habitEditRepository.execute({
|
||||
habitEditData,
|
||||
})
|
||||
return habit
|
||||
}
|
||||
}
|
56
domain/use-cases/HabitGoalProgressUpdate.ts
Normal file
56
domain/use-cases/HabitGoalProgressUpdate.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import type { GoalProgress } from "../entities/Goal"
|
||||
import type { HabitHistory } from "../entities/HabitHistory"
|
||||
import type { HabitProgress } from "../entities/HabitProgress"
|
||||
import type { HabitProgressCreateRepository } from "../repositories/HabitProgressCreate"
|
||||
import type { HabitProgressUpdateRepository } from "../repositories/HabitProgressUpdate"
|
||||
|
||||
export interface HabitGoalProgressUpdateUseCaseOptions {
|
||||
date: Date
|
||||
goalProgress: GoalProgress
|
||||
habitHistory: HabitHistory
|
||||
}
|
||||
|
||||
export interface HabitGoalProgressUpdateUseCaseDependencyOptions {
|
||||
habitProgressCreateRepository: HabitProgressCreateRepository
|
||||
habitProgressUpdateRepository: HabitProgressUpdateRepository
|
||||
}
|
||||
|
||||
export class HabitGoalProgressUpdateUseCase
|
||||
implements HabitGoalProgressUpdateUseCaseDependencyOptions
|
||||
{
|
||||
public habitProgressCreateRepository: HabitProgressCreateRepository
|
||||
public habitProgressUpdateRepository: HabitProgressUpdateRepository
|
||||
|
||||
public constructor(options: HabitGoalProgressUpdateUseCaseDependencyOptions) {
|
||||
this.habitProgressCreateRepository = options.habitProgressCreateRepository
|
||||
this.habitProgressUpdateRepository = options.habitProgressUpdateRepository
|
||||
}
|
||||
|
||||
public async execute(
|
||||
options: HabitGoalProgressUpdateUseCaseOptions,
|
||||
): Promise<HabitProgress> {
|
||||
const { date, goalProgress, habitHistory } = options
|
||||
|
||||
if (goalProgress.isBoolean()) {
|
||||
const currentHabitProgress = habitHistory.getProgressesByDate(date)[0]
|
||||
if (currentHabitProgress == null) {
|
||||
return await this.habitProgressCreateRepository.execute({
|
||||
habitProgressData: {
|
||||
date,
|
||||
goalProgress,
|
||||
habitId: habitHistory.habit.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
return await this.habitProgressUpdateRepository.execute({
|
||||
habitProgressData: {
|
||||
date,
|
||||
goalProgress,
|
||||
id: currentHabitProgress.id,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
throw new Error("Not implemented")
|
||||
}
|
||||
}
|
@ -8,6 +8,11 @@ import { supabaseClient } from "./supabase/supabase"
|
||||
import { AuthenticationPresenter } from "@/presentation/presenters/Authentication"
|
||||
import { HabitCreateSupabaseRepository } from "./supabase/repositories/HabitCreate"
|
||||
import { HabitCreateUseCase } from "@/domain/use-cases/HabitCreate"
|
||||
import { HabitEditSupabaseRepository } from "./supabase/repositories/HabitEdit"
|
||||
import { HabitEditUseCase } from "@/domain/use-cases/HabitEdit"
|
||||
import { HabitProgressCreateSupabaseRepository } from "./supabase/repositories/HabitProgressCreate"
|
||||
import { HabitProgressUpdateSupabaseRepository } from "./supabase/repositories/HabitProgressUpdate"
|
||||
import { HabitGoalProgressUpdateUseCase } from "@/domain/use-cases/HabitGoalProgressUpdate"
|
||||
|
||||
/**
|
||||
* Repositories
|
||||
@ -25,6 +30,19 @@ const getHabitsByUserIdRepository = new GetHabitsByUserIdSupabaseRepository({
|
||||
const habitCreateRepository = new HabitCreateSupabaseRepository({
|
||||
supabaseClient,
|
||||
})
|
||||
const habitEditRepository = new HabitEditSupabaseRepository({
|
||||
supabaseClient,
|
||||
})
|
||||
const habitProgressCreateRepository = new HabitProgressCreateSupabaseRepository(
|
||||
{
|
||||
supabaseClient,
|
||||
},
|
||||
)
|
||||
const habitProgressUpdateRepository = new HabitProgressUpdateSupabaseRepository(
|
||||
{
|
||||
supabaseClient,
|
||||
},
|
||||
)
|
||||
|
||||
/**
|
||||
* Use Cases
|
||||
@ -39,6 +57,13 @@ const retrieveHabitsTrackerUseCase = new RetrieveHabitsTrackerUseCase({
|
||||
getHabitProgressHistoryRepository: getHabitProgressesRepository,
|
||||
getHabitsByUserIdRepository,
|
||||
})
|
||||
const habitEditUseCase = new HabitEditUseCase({
|
||||
habitEditRepository,
|
||||
})
|
||||
const habitGoalProgressUpdateUseCase = new HabitGoalProgressUpdateUseCase({
|
||||
habitProgressCreateRepository,
|
||||
habitProgressUpdateRepository,
|
||||
})
|
||||
|
||||
/**
|
||||
* Presenters
|
||||
@ -49,4 +74,6 @@ export const authenticationPresenter = new AuthenticationPresenter({
|
||||
export const habitsTrackerPresenter = new HabitsTrackerPresenter({
|
||||
retrieveHabitsTrackerUseCase,
|
||||
habitCreateUseCase,
|
||||
habitEditUseCase,
|
||||
habitGoalProgressUpdateUseCase,
|
||||
})
|
||||
|
49
infrastructure/supabase/repositories/HabitEdit.ts
Normal file
49
infrastructure/supabase/repositories/HabitEdit.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { Habit } from "@/domain/entities/Habit"
|
||||
import type { HabitEditRepository } from "@/domain/repositories/HabitEdit"
|
||||
import { SupabaseRepository } from "./_SupabaseRepository"
|
||||
import { Goal } from "@/domain/entities/Goal"
|
||||
|
||||
export class HabitEditSupabaseRepository
|
||||
extends SupabaseRepository
|
||||
implements HabitEditRepository
|
||||
{
|
||||
public execute: HabitEditRepository["execute"] = async (options) => {
|
||||
const { habitEditData } = options
|
||||
const { data, error } = await this.supabaseClient
|
||||
.from("habits")
|
||||
.update({
|
||||
name: habitEditData.name,
|
||||
color: habitEditData.color,
|
||||
icon: habitEditData.icon,
|
||||
})
|
||||
.eq("id", habitEditData.id)
|
||||
.select("*")
|
||||
const updatedHabit = data?.[0]
|
||||
if (error != null || updatedHabit == null) {
|
||||
throw new Error(error?.message ?? "Failed to edit habit.")
|
||||
}
|
||||
const habit = new Habit({
|
||||
id: updatedHabit.id.toString(),
|
||||
userId: updatedHabit.user_id.toString(),
|
||||
name: updatedHabit.name,
|
||||
icon: updatedHabit.icon,
|
||||
goal: Goal.create({
|
||||
frequency: updatedHabit.goal_frequency,
|
||||
target:
|
||||
updatedHabit.goal_target != null &&
|
||||
updatedHabit.goal_target_unit != null
|
||||
? {
|
||||
type: "numeric",
|
||||
value: updatedHabit.goal_target,
|
||||
unit: updatedHabit.goal_target_unit,
|
||||
}
|
||||
: {
|
||||
type: "boolean",
|
||||
},
|
||||
}),
|
||||
color: updatedHabit.color,
|
||||
startDate: new Date(updatedHabit.start_date),
|
||||
})
|
||||
return habit
|
||||
}
|
||||
}
|
38
infrastructure/supabase/repositories/HabitProgressCreate.ts
Normal file
38
infrastructure/supabase/repositories/HabitProgressCreate.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import type { HabitProgressCreateRepository } from "@/domain/repositories/HabitProgressCreate"
|
||||
import { SupabaseRepository } from "./_SupabaseRepository"
|
||||
import { HabitProgress } from "@/domain/entities/HabitProgress"
|
||||
|
||||
export class HabitProgressCreateSupabaseRepository
|
||||
extends SupabaseRepository
|
||||
implements HabitProgressCreateRepository
|
||||
{
|
||||
public execute: HabitProgressCreateRepository["execute"] = async (
|
||||
options,
|
||||
) => {
|
||||
const { habitProgressData } = options
|
||||
const { goalProgress, date, habitId } = habitProgressData
|
||||
let goalProgressValue = goalProgress.isCompleted() ? 1 : 0
|
||||
if (goalProgress.isNumeric()) {
|
||||
goalProgressValue = goalProgress.progress
|
||||
}
|
||||
const { data, error } = await this.supabaseClient
|
||||
.from("habits_progresses")
|
||||
.insert({
|
||||
habit_id: Number(habitId),
|
||||
date: date.toISOString(),
|
||||
goal_progress: goalProgressValue,
|
||||
})
|
||||
.select("*")
|
||||
const insertedProgress = data?.[0]
|
||||
if (error != null || insertedProgress == null) {
|
||||
throw new Error(error?.message ?? "Failed to create habit progress.")
|
||||
}
|
||||
const habitProgress = new HabitProgress({
|
||||
id: insertedProgress.id.toString(),
|
||||
habitId: insertedProgress.habit_id.toString(),
|
||||
date: new Date(insertedProgress.date),
|
||||
goalProgress,
|
||||
})
|
||||
return habitProgress
|
||||
}
|
||||
}
|
38
infrastructure/supabase/repositories/HabitProgressUpdate.ts
Normal file
38
infrastructure/supabase/repositories/HabitProgressUpdate.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import type { HabitProgressUpdateRepository } from "@/domain/repositories/HabitProgressUpdate"
|
||||
import { SupabaseRepository } from "./_SupabaseRepository"
|
||||
import { HabitProgress } from "@/domain/entities/HabitProgress"
|
||||
|
||||
export class HabitProgressUpdateSupabaseRepository
|
||||
extends SupabaseRepository
|
||||
implements HabitProgressUpdateRepository
|
||||
{
|
||||
public execute: HabitProgressUpdateRepository["execute"] = async (
|
||||
options,
|
||||
) => {
|
||||
const { habitProgressData } = options
|
||||
const { id, goalProgress, date } = habitProgressData
|
||||
let goalProgressValue = goalProgress.isCompleted() ? 1 : 0
|
||||
if (goalProgress.isNumeric()) {
|
||||
goalProgressValue = goalProgress.progress
|
||||
}
|
||||
const { data, error } = await this.supabaseClient
|
||||
.from("habits_progresses")
|
||||
.update({
|
||||
date: date.toISOString(),
|
||||
goal_progress: goalProgressValue,
|
||||
})
|
||||
.eq("id", id)
|
||||
.select("*")
|
||||
const insertedProgress = data?.[0]
|
||||
if (error != null || insertedProgress == null) {
|
||||
throw new Error(error?.message ?? "Failed to update habit progress.")
|
||||
}
|
||||
const habitProgress = new HabitProgress({
|
||||
id: insertedProgress.id.toString(),
|
||||
habitId: insertedProgress.habit_id.toString(),
|
||||
date: new Date(insertedProgress.date),
|
||||
goalProgress,
|
||||
})
|
||||
return habitProgress
|
||||
}
|
||||
}
|
333
package-lock.json
generated
333
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "p61-project",
|
||||
"version": "1.0.0-staging.1",
|
||||
"version": "1.0.0-staging.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "p61-project",
|
||||
"version": "1.0.0-staging.1",
|
||||
"version": "1.0.0-staging.2",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@expo/vector-icons": "14.0.0",
|
||||
@ -17,8 +17,8 @@
|
||||
"@hookform/resolvers": "3.3.4",
|
||||
"@react-native-async-storage/async-storage": "1.21.0",
|
||||
"@react-navigation/native": "6.1.16",
|
||||
"@supabase/supabase-js": "2.42.0",
|
||||
"expo": "50.0.14",
|
||||
"@supabase/supabase-js": "2.42.1",
|
||||
"expo": "50.0.15",
|
||||
"expo-font": "11.10.3",
|
||||
"expo-linking": "6.2.2",
|
||||
"expo-router": "3.4.8",
|
||||
@ -27,6 +27,7 @@
|
||||
"expo-system-ui": "2.9.3",
|
||||
"expo-web-browser": "12.8.2",
|
||||
"immer": "10.0.4",
|
||||
"lottie-react-native": "6.5.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-hook-form": "7.51.2",
|
||||
@ -53,11 +54,11 @@
|
||||
"@total-typescript/ts-reset": "0.5.1",
|
||||
"@tsconfig/strictest": "2.0.5",
|
||||
"@types/jest": "29.5.12",
|
||||
"@types/node": "20.12.4",
|
||||
"@types/react": "18.2.74",
|
||||
"@types/node": "20.12.7",
|
||||
"@types/react": "18.2.76",
|
||||
"@types/react-test-renderer": "18.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "7.5.0",
|
||||
"@typescript-eslint/parser": "7.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.6.0",
|
||||
"@typescript-eslint/parser": "7.6.0",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-conventions": "14.1.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
@ -75,7 +76,7 @@
|
||||
"lint-staged": "15.2.2",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"supabase": "1.153.4",
|
||||
"typescript": "5.4.4"
|
||||
"typescript": "5.4.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@aashutoshrathi/word-wrap": {
|
||||
@ -3224,14 +3225,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/env": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@expo/env/-/env-0.2.2.tgz",
|
||||
"integrity": "sha512-m9nGuaSpzdvMzevQ1H60FWgf4PG5s4J0dfKUzdAGnDu7sMUerY/yUeDaA4+OBo3vBwGVQ+UHcQS9vPSMBNaPcg==",
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@expo/env/-/env-0.2.3.tgz",
|
||||
"integrity": "sha512-a+uJ/e6MAVxPVVN/HbXU5qxzdqrqDwNQYxCfxtAufgmd5VZj54e5f3TJA3LEEUW3pTSZR8xK0H0EtVN297AZnw==",
|
||||
"dependencies": {
|
||||
"chalk": "^4.0.0",
|
||||
"debug": "^4.3.4",
|
||||
"dotenv": "~16.0.3",
|
||||
"dotenv-expand": "~10.0.0",
|
||||
"dotenv": "~16.4.5",
|
||||
"dotenv-expand": "~11.0.6",
|
||||
"getenv": "^1.0.0"
|
||||
}
|
||||
},
|
||||
@ -8030,9 +8031,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/postgrest-js": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.15.0.tgz",
|
||||
"integrity": "sha512-U4bwBOrhsXWqDjZiYNbVqMBtRGgIIYE0kE5ZNSwsIbeBWfr/UxOMrnkIQUBGIZRhpYW/tw1WnTdRl1AGNyaxcw==",
|
||||
"version": "1.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.15.1.tgz",
|
||||
"integrity": "sha512-H/4PABAAgMrEIo7oewUZiZMy422Pgc19OLVjU8Vwopcvfr3GD7h8Re4VXtiaPPZqc/2z/k3PnyguFnoKIB7fkA==",
|
||||
"dependencies": {
|
||||
"@supabase/node-fetch": "^2.6.14"
|
||||
}
|
||||
@ -8057,14 +8058,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/supabase-js": {
|
||||
"version": "2.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.42.0.tgz",
|
||||
"integrity": "sha512-1PDqJiA4iG45w3AAu6xkccJ3wPqlGJUoz9CPhScRLLTStxhewYhz0mjryTpXz1kgtNHdUAsirALreezn8UZMjA==",
|
||||
"version": "2.42.1",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.42.1.tgz",
|
||||
"integrity": "sha512-y05XIC6wChApz8BWE2TLUo6SBGp9ttbjhQ9DcQXI897vI3RRPIjm3wZqUoZiexUco+kgt3Em53+m55nB8Um6Sg==",
|
||||
"dependencies": {
|
||||
"@supabase/auth-js": "2.63.0",
|
||||
"@supabase/functions-js": "2.2.2",
|
||||
"@supabase/node-fetch": "2.6.15",
|
||||
"@supabase/postgrest-js": "1.15.0",
|
||||
"@supabase/postgrest-js": "1.15.1",
|
||||
"@supabase/realtime-js": "2.9.3",
|
||||
"@supabase/storage-js": "2.5.5"
|
||||
}
|
||||
@ -8235,9 +8236,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.12.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.4.tgz",
|
||||
"integrity": "sha512-E+Fa9z3wSQpzgYQdYmme5X3OTuejnnTx88A6p6vkkJosR3KBz+HpE3kqNm98VE6cfLFcISx7zW7MsJkH6KwbTw==",
|
||||
"version": "20.12.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz",
|
||||
"integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==",
|
||||
"dependencies": {
|
||||
"undici-types": "~5.26.4"
|
||||
}
|
||||
@ -8259,9 +8260,9 @@
|
||||
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.2.74",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.74.tgz",
|
||||
"integrity": "sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==",
|
||||
"version": "18.2.76",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.76.tgz",
|
||||
"integrity": "sha512-T6z/v7YxpswDM61Vq5KoSPTJqCkroJfsDIsvXCr4+qOY6gik5Ju4w0jf67cpC5z7ydOnp/E0V0W08pDRy8u9Xw==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^3.0.2"
|
||||
@ -8332,22 +8333,22 @@
|
||||
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz",
|
||||
"integrity": "sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.6.0.tgz",
|
||||
"integrity": "sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.5.1",
|
||||
"@typescript-eslint/scope-manager": "7.5.0",
|
||||
"@typescript-eslint/type-utils": "7.5.0",
|
||||
"@typescript-eslint/utils": "7.5.0",
|
||||
"@typescript-eslint/visitor-keys": "7.5.0",
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "7.6.0",
|
||||
"@typescript-eslint/type-utils": "7.6.0",
|
||||
"@typescript-eslint/utils": "7.6.0",
|
||||
"@typescript-eslint/visitor-keys": "7.6.0",
|
||||
"debug": "^4.3.4",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.2.4",
|
||||
"ignore": "^5.3.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
"semver": "^7.5.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
"semver": "^7.6.0",
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@ -8400,15 +8401,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.5.0.tgz",
|
||||
"integrity": "sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.6.0.tgz",
|
||||
"integrity": "sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "7.5.0",
|
||||
"@typescript-eslint/types": "7.5.0",
|
||||
"@typescript-eslint/typescript-estree": "7.5.0",
|
||||
"@typescript-eslint/visitor-keys": "7.5.0",
|
||||
"@typescript-eslint/scope-manager": "7.6.0",
|
||||
"@typescript-eslint/types": "7.6.0",
|
||||
"@typescript-eslint/typescript-estree": "7.6.0",
|
||||
"@typescript-eslint/visitor-keys": "7.6.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@ -8428,13 +8429,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz",
|
||||
"integrity": "sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.6.0.tgz",
|
||||
"integrity": "sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.5.0",
|
||||
"@typescript-eslint/visitor-keys": "7.5.0"
|
||||
"@typescript-eslint/types": "7.6.0",
|
||||
"@typescript-eslint/visitor-keys": "7.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@ -8445,15 +8446,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz",
|
||||
"integrity": "sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.6.0.tgz",
|
||||
"integrity": "sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "7.5.0",
|
||||
"@typescript-eslint/utils": "7.5.0",
|
||||
"@typescript-eslint/typescript-estree": "7.6.0",
|
||||
"@typescript-eslint/utils": "7.6.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@ -8472,9 +8473,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.5.0.tgz",
|
||||
"integrity": "sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.6.0.tgz",
|
||||
"integrity": "sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@ -8485,19 +8486,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz",
|
||||
"integrity": "sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.6.0.tgz",
|
||||
"integrity": "sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.5.0",
|
||||
"@typescript-eslint/visitor-keys": "7.5.0",
|
||||
"@typescript-eslint/types": "7.6.0",
|
||||
"@typescript-eslint/visitor-keys": "7.6.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
"minimatch": "9.0.3",
|
||||
"semver": "^7.5.4",
|
||||
"ts-api-utils": "^1.0.1"
|
||||
"minimatch": "^9.0.4",
|
||||
"semver": "^7.6.0",
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@ -8546,18 +8547,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.5.0.tgz",
|
||||
"integrity": "sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.6.0.tgz",
|
||||
"integrity": "sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@types/json-schema": "^7.0.12",
|
||||
"@types/semver": "^7.5.0",
|
||||
"@typescript-eslint/scope-manager": "7.5.0",
|
||||
"@typescript-eslint/types": "7.5.0",
|
||||
"@typescript-eslint/typescript-estree": "7.5.0",
|
||||
"semver": "^7.5.4"
|
||||
"@types/json-schema": "^7.0.15",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@typescript-eslint/scope-manager": "7.6.0",
|
||||
"@typescript-eslint/types": "7.6.0",
|
||||
"@typescript-eslint/typescript-estree": "7.6.0",
|
||||
"semver": "^7.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@ -8604,13 +8605,13 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz",
|
||||
"integrity": "sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==",
|
||||
"version": "7.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.6.0.tgz",
|
||||
"integrity": "sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.5.0",
|
||||
"eslint-visitor-keys": "^3.4.1"
|
||||
"@typescript-eslint/types": "7.6.0",
|
||||
"eslint-visitor-keys": "^3.4.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@ -8948,7 +8949,6 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
|
||||
"integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.5",
|
||||
"is-array-buffer": "^3.0.4"
|
||||
@ -9099,7 +9099,6 @@
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz",
|
||||
"integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"array-buffer-byte-length": "^1.0.1",
|
||||
"call-bind": "^1.0.5",
|
||||
@ -9948,9 +9947,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001605",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001605.tgz",
|
||||
"integrity": "sha512-nXwGlFWo34uliI9z3n6Qc0wZaf7zaZWA1CPZ169La5mV3I/gem7bst0vr5XQH5TJXZIMfDeZyOrZnSlVzKxxHQ==",
|
||||
"version": "1.0.30001608",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001608.tgz",
|
||||
"integrity": "sha512-cjUJTQkk9fQlJR2s4HMuPMvTiRggl0rAVMtthQuyOlDWuqHXqN8azLq+pi8B2TjwKJ32diHjUqRIKeFX4z1FoA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -10833,7 +10832,6 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
|
||||
"integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.6",
|
||||
"es-errors": "^1.3.0",
|
||||
@ -10850,7 +10848,6 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz",
|
||||
"integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"es-errors": "^1.3.0",
|
||||
@ -10867,7 +10864,6 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz",
|
||||
"integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.6",
|
||||
"es-errors": "^1.3.0",
|
||||
@ -10924,9 +10920,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dedent": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz",
|
||||
"integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==",
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
|
||||
"integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"babel-plugin-macros": "^3.1.0"
|
||||
@ -11131,7 +11127,6 @@
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
|
||||
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.0",
|
||||
@ -11351,19 +11346,28 @@
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
|
||||
"integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
|
||||
"version": "16.4.5",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
|
||||
"integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv-expand": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz",
|
||||
"integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==",
|
||||
"version": "11.0.6",
|
||||
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz",
|
||||
"integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==",
|
||||
"dependencies": {
|
||||
"dotenv": "^16.4.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/ee-first": {
|
||||
@ -11372,9 +11376,9 @@
|
||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.727",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.727.tgz",
|
||||
"integrity": "sha512-brpv4KTeC4g0Fx2FeIKytLd4UGn1zBQq5Lauy7zEWT9oqkaj5mgsxblEZIAOf1HHLlXxzr6adGViiBy5Z39/CA=="
|
||||
"version": "1.4.733",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.733.tgz",
|
||||
"integrity": "sha512-gUI9nhI2iBGF0OaYYLKOaOtliFMl+Bt1rY7VmEjwxOxqoYLub/D9xmduPEhbw2imE6gYkJKhIE5it+KE2ulVxQ=="
|
||||
},
|
||||
"node_modules/emittery": {
|
||||
"version": "0.13.1",
|
||||
@ -11439,9 +11443,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/envinfo": {
|
||||
"version": "7.11.1",
|
||||
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.1.tgz",
|
||||
"integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==",
|
||||
"version": "7.12.0",
|
||||
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.12.0.tgz",
|
||||
"integrity": "sha512-Iw9rQJBGpJRd3rwXm9ft/JiGoAZmLxxJZELYDQoPRZ4USVhkKtIcNBPw6U+/K2mBpaqM25JSV6Yl4Az9vO2wJg==",
|
||||
"bin": {
|
||||
"envinfo": "dist/cli.js"
|
||||
},
|
||||
@ -11486,7 +11490,6 @@
|
||||
"version": "1.23.3",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
|
||||
"integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"array-buffer-byte-length": "^1.0.1",
|
||||
"arraybuffer.prototype.slice": "^1.0.3",
|
||||
@ -11590,7 +11593,6 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
|
||||
"integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
@ -11602,7 +11604,6 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz",
|
||||
"integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
@ -11625,7 +11626,6 @@
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
|
||||
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-callable": "^1.1.4",
|
||||
"is-date-object": "^1.0.1",
|
||||
@ -12499,9 +12499,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/expo": {
|
||||
"version": "50.0.14",
|
||||
"resolved": "https://registry.npmjs.org/expo/-/expo-50.0.14.tgz",
|
||||
"integrity": "sha512-yLPdxCMVAbmeEIpzzyAuJ79wvr6ToDDtQmuLDMAgWtjqP8x3CGddXxUe07PpKEQgzwJabdHvCLP5Bv94wMFIjQ==",
|
||||
"version": "50.0.15",
|
||||
"resolved": "https://registry.npmjs.org/expo/-/expo-50.0.15.tgz",
|
||||
"integrity": "sha512-tsyRmMHjA8lPlM7AsqH1smSH8hzmn1+x/vsP+xgbKYJTGtYccdY/wsm6P84VJWeK5peWSVqrWNos+YuPqXKLSQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.0",
|
||||
"@expo/cli": "0.17.8",
|
||||
@ -12515,7 +12515,7 @@
|
||||
"expo-font": "~11.10.3",
|
||||
"expo-keep-awake": "~12.8.2",
|
||||
"expo-modules-autolinking": "1.10.3",
|
||||
"expo-modules-core": "1.11.12",
|
||||
"expo-modules-core": "1.11.13",
|
||||
"fbemitter": "^3.0.0",
|
||||
"whatwg-url-without-unicode": "8.0.0-3"
|
||||
},
|
||||
@ -12748,9 +12748,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/expo-modules-core": {
|
||||
"version": "1.11.12",
|
||||
"resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.11.12.tgz",
|
||||
"integrity": "sha512-/e8g4kis0pFLer7C0PLyx98AfmztIM6gU9jLkYnB1pU9JAfQf904XEi3bmszO7uoteBQwSL6FLp1m3TePKhDaA==",
|
||||
"version": "1.11.13",
|
||||
"resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.11.13.tgz",
|
||||
"integrity": "sha512-2H5qrGUvmLzmJNPDOnovH1Pfk5H/S/V0BifBmOQyDc9aUh9LaDwkqnChZGIXv8ZHDW8JRlUW0QqyWxTggkbw1A==",
|
||||
"dependencies": {
|
||||
"invariant": "^2.2.4"
|
||||
}
|
||||
@ -13320,7 +13320,6 @@
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
|
||||
"integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"define-properties": "^1.2.0",
|
||||
@ -13338,7 +13337,6 @@
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
|
||||
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
@ -13422,7 +13420,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz",
|
||||
"integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.5",
|
||||
"es-errors": "^1.3.0",
|
||||
@ -13538,7 +13535,6 @@
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
|
||||
"integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"define-properties": "^1.1.3"
|
||||
},
|
||||
@ -13616,7 +13612,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
|
||||
"integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
|
||||
"dev": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
@ -14032,7 +14027,6 @@
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
|
||||
"integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"hasown": "^2.0.0",
|
||||
@ -14085,7 +14079,6 @@
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
|
||||
"integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"get-intrinsic": "^1.2.1"
|
||||
@ -14121,7 +14114,6 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
|
||||
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-bigints": "^1.0.1"
|
||||
},
|
||||
@ -14133,7 +14125,6 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
|
||||
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"has-tostringtag": "^1.0.0"
|
||||
@ -14191,7 +14182,6 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz",
|
||||
"integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-typed-array": "^1.1.13"
|
||||
},
|
||||
@ -14206,7 +14196,6 @@
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
|
||||
"integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-tostringtag": "^1.0.0"
|
||||
},
|
||||
@ -14359,7 +14348,6 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
|
||||
"integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@ -14379,7 +14367,6 @@
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
|
||||
"integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-tostringtag": "^1.0.0"
|
||||
},
|
||||
@ -14444,7 +14431,6 @@
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
|
||||
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"has-tostringtag": "^1.0.0"
|
||||
@ -14472,7 +14458,6 @@
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz",
|
||||
"integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7"
|
||||
},
|
||||
@ -14499,7 +14484,6 @@
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
|
||||
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-tostringtag": "^1.0.0"
|
||||
},
|
||||
@ -14514,7 +14498,6 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
|
||||
"integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.2"
|
||||
},
|
||||
@ -14589,7 +14572,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
|
||||
"integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2"
|
||||
},
|
||||
@ -14627,8 +14609,7 @@
|
||||
"node_modules/isarray": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
|
||||
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
|
||||
},
|
||||
"node_modules/isexe": {
|
||||
"version": "2.0.0",
|
||||
@ -18035,6 +18016,29 @@
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/lottie-react-native": {
|
||||
"version": "6.5.1",
|
||||
"resolved": "https://registry.npmjs.org/lottie-react-native/-/lottie-react-native-6.5.1.tgz",
|
||||
"integrity": "sha512-pjih71P6qX6Ax5ucUBA+YJO7+fnveI581Bd8LmYeARm3spq3AnoGzEkrWaieM8odnK6WI4d5dwEJsxge/QjFPw==",
|
||||
"peerDependencies": {
|
||||
"@dotlottie/react-player": "^1.6.1",
|
||||
"@lottiefiles/react-lottie-player": "^3.5.3",
|
||||
"react": "*",
|
||||
"react-native": ">=0.46",
|
||||
"react-native-windows": ">=0.63.x"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@dotlottie/react-player": {
|
||||
"optional": true
|
||||
},
|
||||
"@lottiefiles/react-lottie-player": {
|
||||
"optional": true
|
||||
},
|
||||
"react-native-windows": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@ -18737,9 +18741,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
|
||||
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
|
||||
"version": "9.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
|
||||
"integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
@ -19273,7 +19277,6 @@
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
@ -19282,7 +19285,6 @@
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
|
||||
"integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.5",
|
||||
"define-properties": "^1.2.1",
|
||||
@ -21155,7 +21157,6 @@
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz",
|
||||
"integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.6",
|
||||
"define-properties": "^1.2.1",
|
||||
@ -21420,7 +21421,6 @@
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz",
|
||||
"integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
@ -21449,7 +21449,6 @@
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
|
||||
"integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.6",
|
||||
"es-errors": "^1.3.0",
|
||||
@ -21642,7 +21641,6 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
|
||||
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"define-data-property": "^1.1.4",
|
||||
"es-errors": "^1.3.0",
|
||||
@ -22161,7 +22159,6 @@
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz",
|
||||
"integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"define-properties": "^1.2.1",
|
||||
@ -22179,7 +22176,6 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz",
|
||||
"integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"define-properties": "^1.2.1",
|
||||
@ -22193,7 +22189,6 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
|
||||
"integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"define-properties": "^1.2.1",
|
||||
@ -22815,9 +22810,14 @@
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"node_modules/traverse": {
|
||||
"version": "0.6.8",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz",
|
||||
"integrity": "sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==",
|
||||
"version": "0.6.9",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.9.tgz",
|
||||
"integrity": "sha512-7bBrcF+/LQzSgFmT0X5YclVqQxtv7TDJ1f8Wj7ibBu/U6BMLeOpUxuZjV7rMc44UtKxlnMFigdhFAIszSX1DMg==",
|
||||
"dependencies": {
|
||||
"gopd": "^1.0.1",
|
||||
"typedarray.prototype.slice": "^1.0.3",
|
||||
"which-typed-array": "^1.1.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@ -22920,7 +22920,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz",
|
||||
"integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"es-errors": "^1.3.0",
|
||||
@ -22934,7 +22933,6 @@
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz",
|
||||
"integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"for-each": "^0.3.3",
|
||||
@ -22953,7 +22951,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz",
|
||||
"integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"available-typed-arrays": "^1.0.7",
|
||||
"call-bind": "^1.0.7",
|
||||
@ -22973,7 +22970,6 @@
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz",
|
||||
"integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"for-each": "^0.3.3",
|
||||
@ -22989,10 +22985,29 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typedarray.prototype.slice": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.3.tgz",
|
||||
"integrity": "sha512-8WbVAQAUlENo1q3c3zZYuy5k9VzBQvp8AX9WOtbvyWlLM1v5JaSRmjubLjzHF4JFtptjH/5c/i95yaElvcjC0A==",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"define-properties": "^1.2.1",
|
||||
"es-abstract": "^1.23.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"typed-array-buffer": "^1.0.2",
|
||||
"typed-array-byte-offset": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.4.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.4.tgz",
|
||||
"integrity": "sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==",
|
||||
"version": "5.4.5",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
|
||||
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
@ -23028,7 +23043,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
|
||||
"integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.2",
|
||||
"has-bigints": "^1.0.2",
|
||||
@ -23432,7 +23446,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
|
||||
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-bigint": "^1.0.1",
|
||||
"is-boolean-object": "^1.1.0",
|
||||
|
17
package.json
17
package.json
@ -2,7 +2,7 @@
|
||||
"name": "p61-project",
|
||||
"private": true,
|
||||
"main": "expo-router/entry",
|
||||
"version": "1.0.0-staging.1",
|
||||
"version": "1.0.0-staging.2",
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"android": "expo start --android",
|
||||
@ -27,8 +27,8 @@
|
||||
"@hookform/resolvers": "3.3.4",
|
||||
"@react-native-async-storage/async-storage": "1.21.0",
|
||||
"@react-navigation/native": "6.1.16",
|
||||
"@supabase/supabase-js": "2.42.0",
|
||||
"expo": "50.0.14",
|
||||
"@supabase/supabase-js": "2.42.1",
|
||||
"expo": "50.0.15",
|
||||
"expo-font": "11.10.3",
|
||||
"expo-linking": "6.2.2",
|
||||
"expo-router": "3.4.8",
|
||||
@ -37,6 +37,7 @@
|
||||
"expo-system-ui": "2.9.3",
|
||||
"expo-web-browser": "12.8.2",
|
||||
"immer": "10.0.4",
|
||||
"lottie-react-native": "6.5.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-hook-form": "7.51.2",
|
||||
@ -63,11 +64,11 @@
|
||||
"@total-typescript/ts-reset": "0.5.1",
|
||||
"@tsconfig/strictest": "2.0.5",
|
||||
"@types/jest": "29.5.12",
|
||||
"@types/node": "20.12.4",
|
||||
"@types/react": "18.2.74",
|
||||
"@types/node": "20.12.7",
|
||||
"@types/react": "18.2.76",
|
||||
"@types/react-test-renderer": "18.0.7",
|
||||
"@typescript-eslint/eslint-plugin": "7.5.0",
|
||||
"@typescript-eslint/parser": "7.5.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.6.0",
|
||||
"@typescript-eslint/parser": "7.6.0",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-conventions": "14.1.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
@ -85,6 +86,6 @@
|
||||
"lint-staged": "15.2.2",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"supabase": "1.153.4",
|
||||
"typescript": "5.4.4"
|
||||
"typescript": "5.4.5"
|
||||
}
|
||||
}
|
||||
|
5382
presentation/assets/confetti.json
Normal file
5382
presentation/assets/confetti.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,9 +7,14 @@ import type {
|
||||
RetrieveHabitsTrackerUseCase,
|
||||
RetrieveHabitsTrackerUseCaseOptions,
|
||||
} from "@/domain/use-cases/RetrieveHabitsTracker"
|
||||
import type { HabitCreateData } from "@/domain/entities/Habit"
|
||||
import type { HabitCreateData, HabitEditData } from "@/domain/entities/Habit"
|
||||
import { getErrorsFieldsFromZodError } from "../../utils/zod"
|
||||
import type { HabitCreateUseCase } from "@/domain/use-cases/HabitCreate"
|
||||
import type { HabitEditUseCase } from "@/domain/use-cases/HabitEdit"
|
||||
import type {
|
||||
HabitGoalProgressUpdateUseCase,
|
||||
HabitGoalProgressUpdateUseCaseOptions,
|
||||
} from "@/domain/use-cases/HabitGoalProgressUpdate"
|
||||
|
||||
export interface HabitsTrackerPresenterState {
|
||||
habitsTracker: HabitsTracker
|
||||
@ -25,11 +30,25 @@ export interface HabitsTrackerPresenterState {
|
||||
global: ErrorGlobal
|
||||
}
|
||||
}
|
||||
|
||||
habitEdit: {
|
||||
state: FetchState
|
||||
errors: {
|
||||
fields: Array<keyof HabitEditData>
|
||||
global: ErrorGlobal
|
||||
}
|
||||
}
|
||||
|
||||
habitGoalProgressUpdate: {
|
||||
state: FetchState
|
||||
}
|
||||
}
|
||||
|
||||
export interface HabitsTrackerPresenterOptions {
|
||||
retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase
|
||||
habitCreateUseCase: HabitCreateUseCase
|
||||
habitEditUseCase: HabitEditUseCase
|
||||
habitGoalProgressUpdateUseCase: HabitGoalProgressUpdateUseCase
|
||||
}
|
||||
|
||||
export class HabitsTrackerPresenter
|
||||
@ -38,9 +57,16 @@ export class HabitsTrackerPresenter
|
||||
{
|
||||
public retrieveHabitsTrackerUseCase: RetrieveHabitsTrackerUseCase
|
||||
public habitCreateUseCase: HabitCreateUseCase
|
||||
public habitEditUseCase: HabitEditUseCase
|
||||
public habitGoalProgressUpdateUseCase: HabitGoalProgressUpdateUseCase
|
||||
|
||||
public constructor(options: HabitsTrackerPresenterOptions) {
|
||||
const { retrieveHabitsTrackerUseCase, habitCreateUseCase } = options
|
||||
const {
|
||||
retrieveHabitsTrackerUseCase,
|
||||
habitCreateUseCase,
|
||||
habitEditUseCase,
|
||||
habitGoalProgressUpdateUseCase,
|
||||
} = options
|
||||
const habitsTracker = HabitsTracker.default()
|
||||
super({
|
||||
habitsTracker,
|
||||
@ -52,9 +78,21 @@ export class HabitsTrackerPresenter
|
||||
global: null,
|
||||
},
|
||||
},
|
||||
habitEdit: {
|
||||
state: "idle",
|
||||
errors: {
|
||||
fields: [],
|
||||
global: null,
|
||||
},
|
||||
},
|
||||
habitGoalProgressUpdate: {
|
||||
state: "idle",
|
||||
},
|
||||
})
|
||||
this.retrieveHabitsTrackerUseCase = retrieveHabitsTrackerUseCase
|
||||
this.habitCreateUseCase = habitCreateUseCase
|
||||
this.habitEditUseCase = habitEditUseCase
|
||||
this.habitGoalProgressUpdateUseCase = habitGoalProgressUpdateUseCase
|
||||
}
|
||||
|
||||
public async habitCreate(data: unknown): Promise<FetchState> {
|
||||
@ -86,6 +124,35 @@ export class HabitsTrackerPresenter
|
||||
}
|
||||
}
|
||||
|
||||
public async habitEdit(data: unknown): Promise<FetchState> {
|
||||
try {
|
||||
this.setState((state) => {
|
||||
state.habitEdit.state = "loading"
|
||||
state.habitEdit.errors = {
|
||||
fields: [],
|
||||
global: null,
|
||||
}
|
||||
})
|
||||
const habit = await this.habitEditUseCase.execute(data)
|
||||
this.setState((state) => {
|
||||
state.habitEdit.state = "success"
|
||||
state.habitsTracker.editHabit(habit)
|
||||
})
|
||||
return "success"
|
||||
} catch (error) {
|
||||
this.setState((state) => {
|
||||
state.habitEdit.state = "error"
|
||||
if (error instanceof ZodError) {
|
||||
state.habitEdit.errors.fields =
|
||||
getErrorsFieldsFromZodError<HabitEditData>(error)
|
||||
} else {
|
||||
state.habitEdit.errors.global = "unknown"
|
||||
}
|
||||
})
|
||||
return "error"
|
||||
}
|
||||
}
|
||||
|
||||
public async retrieveHabitsTracker(
|
||||
options: RetrieveHabitsTrackerUseCaseOptions,
|
||||
): Promise<void> {
|
||||
@ -106,4 +173,26 @@ export class HabitsTrackerPresenter
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public async habitUpdateProgress(
|
||||
options: HabitGoalProgressUpdateUseCaseOptions,
|
||||
): Promise<FetchState> {
|
||||
try {
|
||||
this.setState((state) => {
|
||||
state.habitGoalProgressUpdate.state = "loading"
|
||||
})
|
||||
const habitProgress =
|
||||
await this.habitGoalProgressUpdateUseCase.execute(options)
|
||||
this.setState((state) => {
|
||||
state.habitsTracker.updateHabitProgress(habitProgress)
|
||||
state.habitGoalProgressUpdate.state = "success"
|
||||
})
|
||||
return "success"
|
||||
} catch (error) {
|
||||
this.setState((state) => {
|
||||
state.habitGoalProgressUpdate.state = "error"
|
||||
})
|
||||
return "error"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
154
presentation/react/components/HabitEditForm/HabitEditForm.tsx
Normal file
154
presentation/react/components/HabitEditForm/HabitEditForm.tsx
Normal file
@ -0,0 +1,154 @@
|
||||
import { zodResolver } from "@hookform/resolvers/zod"
|
||||
import { useState } from "react"
|
||||
import { Controller, useForm } from "react-hook-form"
|
||||
import { ScrollView, StyleSheet } from "react-native"
|
||||
import { Button, HelperText, Snackbar, TextInput } from "react-native-paper"
|
||||
import { SafeAreaView } from "react-native-safe-area-context"
|
||||
import ColorPicker, {
|
||||
HueSlider,
|
||||
Panel1,
|
||||
Preview,
|
||||
} from "reanimated-color-picker"
|
||||
|
||||
import type { Habit, HabitEditData } from "@/domain/entities/Habit"
|
||||
import { HabitEditSchema } from "@/domain/entities/Habit"
|
||||
import { useHabitsTracker } from "../../contexts/HabitsTracker"
|
||||
|
||||
export interface HabitEditFormProps {
|
||||
habit: Habit
|
||||
}
|
||||
|
||||
export const HabitEditForm: React.FC<HabitEditFormProps> = ({ habit }) => {
|
||||
const { habitEdit, habitsTrackerPresenter } = useHabitsTracker()
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm<HabitEditData>({
|
||||
mode: "onChange",
|
||||
resolver: zodResolver(HabitEditSchema),
|
||||
defaultValues: {
|
||||
id: habit.id,
|
||||
userId: habit.userId,
|
||||
name: habit.name,
|
||||
color: habit.color,
|
||||
icon: habit.icon,
|
||||
},
|
||||
})
|
||||
|
||||
const [isVisibleSnackbar, setIsVisibleSnackbar] = useState(false)
|
||||
|
||||
const onDismissSnackbar = (): void => {
|
||||
setIsVisibleSnackbar(false)
|
||||
}
|
||||
|
||||
const onSubmit = async (data: HabitEditData): Promise<void> => {
|
||||
await habitsTrackerPresenter.habitEdit(data)
|
||||
setIsVisibleSnackbar(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<SafeAreaView>
|
||||
<ScrollView
|
||||
contentContainerStyle={{
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
paddingHorizontal: 20,
|
||||
}}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field: { onChange, onBlur, value } }) => {
|
||||
return (
|
||||
<>
|
||||
<TextInput
|
||||
placeholder="Name"
|
||||
onBlur={onBlur}
|
||||
onChangeText={onChange}
|
||||
value={value}
|
||||
style={[
|
||||
styles.spacing,
|
||||
{
|
||||
width: "90%",
|
||||
},
|
||||
]}
|
||||
mode="outlined"
|
||||
/>
|
||||
{errors.name != null ? (
|
||||
<HelperText type="error" visible style={[{ paddingTop: 0 }]}>
|
||||
{errors.name.type === "too_big"
|
||||
? "Name is too long"
|
||||
: "Name is required"}
|
||||
</HelperText>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}}
|
||||
name="name"
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field: { onChange, value } }) => {
|
||||
return (
|
||||
<ColorPicker
|
||||
style={[styles.spacing, { width: "90%" }]}
|
||||
value={value}
|
||||
onComplete={(value) => {
|
||||
onChange(value.hex)
|
||||
}}
|
||||
>
|
||||
<Preview hideInitialColor />
|
||||
<Panel1 />
|
||||
<HueSlider />
|
||||
</ColorPicker>
|
||||
)
|
||||
}}
|
||||
name="color"
|
||||
/>
|
||||
|
||||
<Controller
|
||||
control={control}
|
||||
render={({ field: { onChange, onBlur, value } }) => {
|
||||
return (
|
||||
<TextInput
|
||||
placeholder="Icon"
|
||||
onBlur={onBlur}
|
||||
onChangeText={onChange}
|
||||
value={value}
|
||||
style={[styles.spacing, { width: "90%" }]}
|
||||
mode="outlined"
|
||||
/>
|
||||
)
|
||||
}}
|
||||
name="icon"
|
||||
/>
|
||||
|
||||
<Button
|
||||
mode="contained"
|
||||
onPress={handleSubmit(onSubmit)}
|
||||
loading={habitEdit.state === "loading"}
|
||||
disabled={habitEdit.state === "loading"}
|
||||
style={[styles.spacing, { width: "90%" }]}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
</ScrollView>
|
||||
|
||||
<Snackbar
|
||||
visible={isVisibleSnackbar}
|
||||
onDismiss={onDismissSnackbar}
|
||||
duration={2_000}
|
||||
>
|
||||
✅ Habit Saved successfully!
|
||||
</Snackbar>
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
spacing: {
|
||||
marginVertical: 16,
|
||||
},
|
||||
})
|
@ -1,21 +1,31 @@
|
||||
import FontAwesome6 from "@expo/vector-icons/FontAwesome6"
|
||||
import { useRouter } from "expo-router"
|
||||
import { useState } from "react"
|
||||
import { View } from "react-native"
|
||||
import { List, Text } from "react-native-paper"
|
||||
import { Checkbox, List, Text } from "react-native-paper"
|
||||
import type LottieView from "lottie-react-native"
|
||||
|
||||
import type { GoalProgress } from "@/domain/entities/Goal"
|
||||
import type { Habit } from "@/domain/entities/Habit"
|
||||
import type { GoalBoolean } from "@/domain/entities/Goal"
|
||||
import { GoalBooleanProgress } from "@/domain/entities/Goal"
|
||||
import type { HabitHistory } from "@/domain/entities/HabitHistory"
|
||||
import { getColorRGBAFromHex } from "@/utils/colors"
|
||||
import { useHabitsTracker } from "../../contexts/HabitsTracker"
|
||||
|
||||
export interface HabitCardProps {
|
||||
habit: Habit
|
||||
goalProgress: GoalProgress
|
||||
habitHistory: HabitHistory
|
||||
selectedDate: Date
|
||||
confettiRef: React.MutableRefObject<LottieView | null>
|
||||
}
|
||||
|
||||
export const HabitCard: React.FC<HabitCardProps> = (props) => {
|
||||
const { habit, goalProgress } = props
|
||||
const { habitHistory, selectedDate, confettiRef } = props
|
||||
const { habit } = habitHistory
|
||||
|
||||
const router = useRouter()
|
||||
const { habitsTrackerPresenter } = useHabitsTracker()
|
||||
|
||||
const goalProgress = habitHistory.getGoalProgressByDate(selectedDate)
|
||||
const [checked, setChecked] = useState(goalProgress.isCompleted())
|
||||
|
||||
const habitColor = getColorRGBAFromHex({
|
||||
hexColor: habit.color,
|
||||
@ -54,15 +64,17 @@ export const HabitCard: React.FC<HabitCardProps> = (props) => {
|
||||
]}
|
||||
left={() => {
|
||||
return (
|
||||
<FontAwesome6
|
||||
size={24}
|
||||
name={habit.icon}
|
||||
style={[
|
||||
{
|
||||
width: 30,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<View style={{ justifyContent: "center", alignItems: "center" }}>
|
||||
<FontAwesome6
|
||||
size={24}
|
||||
name={habit.icon}
|
||||
style={[
|
||||
{
|
||||
width: 30,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}}
|
||||
right={() => {
|
||||
@ -79,9 +91,25 @@ export const HabitCard: React.FC<HabitCardProps> = (props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<View>
|
||||
<Text>{goalProgress.isCompleted() ? "true" : "false"}</Text>
|
||||
</View>
|
||||
<Checkbox
|
||||
color="black"
|
||||
status={checked ? "checked" : "unchecked"}
|
||||
onPress={async () => {
|
||||
const isCheckedNew = !checked
|
||||
setChecked(isCheckedNew)
|
||||
if (isCheckedNew) {
|
||||
confettiRef.current?.play()
|
||||
}
|
||||
await habitsTrackerPresenter.habitUpdateProgress({
|
||||
date: selectedDate,
|
||||
habitHistory,
|
||||
goalProgress: new GoalBooleanProgress({
|
||||
goal: habit.goal as GoalBoolean,
|
||||
progress: isCheckedNew,
|
||||
}),
|
||||
})
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { useState } from "react"
|
||||
import { Dimensions, ScrollView } from "react-native"
|
||||
import LottieView from "lottie-react-native"
|
||||
import { useRef, useState } from "react"
|
||||
import { Dimensions, ScrollView, View } from "react-native"
|
||||
import { Divider, List } from "react-native-paper"
|
||||
|
||||
import type { GoalFrequency } from "@/domain/entities/Goal"
|
||||
import type { HabitsTracker } from "@/domain/entities/HabitsTracker"
|
||||
import confettiJSON from "../../../assets/confetti.json"
|
||||
import { capitalize } from "@/utils/strings"
|
||||
import { HabitCard } from "./HabitCard"
|
||||
|
||||
@ -24,51 +26,85 @@ export const HabitsList: React.FC<HabitsListProps> = (props) => {
|
||||
monthly: true,
|
||||
})
|
||||
|
||||
const confettiRef = useRef<LottieView | null>(null)
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={{
|
||||
paddingHorizontal: 20,
|
||||
width: Dimensions.get("window").width,
|
||||
backgroundColor: "white",
|
||||
}}
|
||||
>
|
||||
<Divider />
|
||||
<List.Section>
|
||||
{frequenciesFiltered.map((frequency) => {
|
||||
return (
|
||||
<List.Accordion
|
||||
expanded={accordionExpanded[frequency]}
|
||||
onPress={() => {
|
||||
setAccordionExpanded((old) => {
|
||||
return {
|
||||
...old,
|
||||
[frequency]: !old[frequency],
|
||||
}
|
||||
})
|
||||
}}
|
||||
key={frequency}
|
||||
title={capitalize(frequency)}
|
||||
titleStyle={[
|
||||
{
|
||||
fontSize: 26,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{habitsTracker.habitsHistory[frequency].map((item) => {
|
||||
const goalProgress = item.getGoalProgressByDate(selectedDate)
|
||||
return (
|
||||
<HabitCard
|
||||
habit={item.habit}
|
||||
goalProgress={goalProgress}
|
||||
key={item.habit.id}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</List.Accordion>
|
||||
)
|
||||
})}
|
||||
</List.Section>
|
||||
</ScrollView>
|
||||
<>
|
||||
<View
|
||||
pointerEvents="none"
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
position: "absolute",
|
||||
zIndex: 100,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<LottieView
|
||||
ref={confettiRef}
|
||||
source={confettiJSON}
|
||||
autoPlay={false}
|
||||
loop={false}
|
||||
style={[
|
||||
{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
},
|
||||
]}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
</View>
|
||||
|
||||
<ScrollView
|
||||
showsVerticalScrollIndicator={false}
|
||||
style={{
|
||||
paddingHorizontal: 20,
|
||||
width: Dimensions.get("window").width,
|
||||
backgroundColor: "white",
|
||||
}}
|
||||
>
|
||||
<Divider />
|
||||
|
||||
<List.Section>
|
||||
{frequenciesFiltered.map((frequency) => {
|
||||
return (
|
||||
<List.Accordion
|
||||
expanded={accordionExpanded[frequency]}
|
||||
onPress={() => {
|
||||
setAccordionExpanded((old) => {
|
||||
return {
|
||||
...old,
|
||||
[frequency]: !old[frequency],
|
||||
}
|
||||
})
|
||||
}}
|
||||
key={frequency}
|
||||
title={capitalize(frequency)}
|
||||
titleStyle={[
|
||||
{
|
||||
fontSize: 26,
|
||||
},
|
||||
]}
|
||||
>
|
||||
{habitsTracker.habitsHistory[frequency].map((item) => {
|
||||
return (
|
||||
<HabitCard
|
||||
habitHistory={item}
|
||||
selectedDate={selectedDate}
|
||||
key={item.habit.id + selectedDate.toISOString()}
|
||||
confettiRef={confettiRef}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</List.Accordion>
|
||||
)
|
||||
})}
|
||||
</List.Section>
|
||||
</ScrollView>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user