From e6e751b0ab77d6d262feca5d802f0098e7c5cd4e Mon Sep 17 00:00:00 2001 From: Ania Misiorek Date: Tue, 24 Oct 2023 20:32:16 -0400 Subject: [PATCH 1/6] implementation --- server/src/controller/setup.go | 7 ++- server/src/controller/task.go | 18 +++++- server/src/controller_new/user.go | 66 ++++++++++++++++++++++ server/src/services/persona.go | 46 +++++++++++++++ server/src/services/user.go | 93 +++++++++++++++++++++++++++++++ server/src/services/validator.go | 20 +++++++ 6 files changed, 244 insertions(+), 6 deletions(-) create mode 100644 server/src/controller_new/user.go create mode 100644 server/src/services/persona.go create mode 100644 server/src/services/user.go create mode 100644 server/src/services/validator.go diff --git a/server/src/controller/setup.go b/server/src/controller/setup.go index 1311a2b..cb96d6f 100644 --- a/server/src/controller/setup.go +++ b/server/src/controller/setup.go @@ -54,10 +54,11 @@ func SetupControllers(e *echo.Echo, db *gorm.DB) { // Task routes e.GET("api/tasks", taskController.GetAllTasks) - e.GET("api/tasks/:id", taskController.GetTask) + e.GET("api/tasks/:tid", taskController.GetTask) e.POST("api/tasks", taskController.CreateTask) - e.PUT("api/tasks/:id", taskController.UpdateTask) - e.DELETE("api/tasks/:id", taskController.DeleteTask) + e.PUT("api/tasks/:tid", taskController.UpdateTask) + e.DELETE("api/tasks/:tid", taskController.DeleteTask) + e.GET("api/tasks/:tid/subtasks", taskController.GetSubtasksFromTask) // SubTask routes e.GET("api/subtasks", subtaskController.GetAllSubtasks) diff --git a/server/src/controller/task.go b/server/src/controller/task.go index ba64d67..2081232 100644 --- a/server/src/controller/task.go +++ b/server/src/controller/task.go @@ -22,7 +22,7 @@ func (t *TaskController) GetAllTasks(c echo.Context) error { func (t *TaskController) GetTask(c echo.Context) error { var task model.Task - taskID := c.Param("id") + taskID := c.Param("tid") t.DB.First(&task, taskID) @@ -53,7 +53,7 @@ func (t *TaskController) CreateTask(c echo.Context) error { func (t *TaskController) UpdateTask(c echo.Context) error { var task model.Task - taskID := c.Param("id") + taskID := c.Param("tid") t.DB.First(&task, taskID) @@ -72,7 +72,7 @@ func (t *TaskController) UpdateTask(c echo.Context) error { func (t *TaskController) DeleteTask(c echo.Context) error { var task model.Task - taskID := c.Param("id") + taskID := c.Param("tid") t.DB.First(&task, taskID) @@ -84,3 +84,15 @@ func (t *TaskController) DeleteTask(c echo.Context) error { return c.JSON(http.StatusOK, "Task deleted") } + +func (t *TaskController) GetSubtasksFromTask(c echo.Context) error { + taskID := c.Param("tid") + + // Retrieve the subtasks related to the task by ID + var subtasks []model.SubTask + if err := t.DB.Where("task_id = ?", taskID).Find(&subtasks).Error; err != nil { + return c.JSON(http.StatusNotFound, "Subtasks not found") + } + + return c.JSON(http.StatusOK, subtasks) +} diff --git a/server/src/controller_new/user.go b/server/src/controller_new/user.go new file mode 100644 index 0000000..41aa4c7 --- /dev/null +++ b/server/src/controller_new/user.go @@ -0,0 +1,66 @@ +package controller_new + +import ( + "net/http" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +type UserController struct { + userService *services.UserService +} + +func NewUserController(userService services.UserService) *UserController { + return &UserController{&userService} +} + +func (u *UserController) GetAllUsers(c echo.Context) error { + users, err := u.userService.GetAllUsers(c) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch users") + } + + return c.JSON(http.StatusOK, users) +} + +func (u *UserController) GetUser(c echo.Context) error { + user, err := u.userService.GetUser(c) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch user") + } + + return c.JSON(http.StatusOK, user) +} + +func (u *UserController) CreateUser(c echo.Context) error { + user, err := u.userService.CreateUser(c) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to create user") + } + + return c.JSON(http.StatusCreated, user) +} + +func (u *UserController) UpdateUser(c echo.Context) error { + user, err := u.userService.UpdateUser(c) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to update user") + } + + return c.JSON(http.StatusOK, user) +} + +func (u *UserController) DeleteUser(c echo.Context) error { + err := u.userService.DeleteUser(c) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to update user") + } + + return c.JSON(http.StatusOK, "User deleted") +} diff --git a/server/src/services/persona.go b/server/src/services/persona.go new file mode 100644 index 0000000..0fa218d --- /dev/null +++ b/server/src/services/persona.go @@ -0,0 +1,46 @@ +package services + +import ( + "server/src/model" + + "github.com/labstack/echo/v4" + "gorm.io/gorm" +) + +type PersonaServices struct { + DB *gorm.DB +} + +func (u *PersonaServices) GetPersonaAllTasks(c echo.Context) ([]map[string]interface{}, error) { + var persona model.Persona + personaID := c.Param("pid") + + if err := u.DB.First(&persona, personaID).Error; err != nil { + return nil, err + } + + // Retrieve tasks related to the persona + var tasks []model.Task + u.DB.Model(&persona).Association("Tasks").Find(&tasks) + + // Create a slice to store the JSON response + var taskList []map[string]interface{} + + // Loop through the tasks and retrieve their related subtasks + for _, task := range tasks { + var subtasks []model.SubTask + if err := u.DB.Where("task_id = ?", task.ID).Find(&subtasks).Error; err != nil { + subtasks = []model.SubTask{} // No subtasks found + } + + // Form the JSON response for each task with its related subtasks + taskInfo := map[string]interface{}{ + "task": task, + "subtasks": subtasks, + } + + taskList = append(taskList, taskInfo) + } + + return taskList, nil +} diff --git a/server/src/services/user.go b/server/src/services/user.go new file mode 100644 index 0000000..ca3b4c8 --- /dev/null +++ b/server/src/services/user.go @@ -0,0 +1,93 @@ +package services + +import ( + "server/src/model" + "time" + + "github.com/labstack/echo/v4" + "gorm.io/gorm" +) + +type UserServiceInterface interface { + GetAllUsers(c echo.Context) ([]model.User, error) + GetUser(c echo.Context) (*model.User, error) + CreateUser(c echo.Context) (*model.User, error) + UpdateUser(c echo.Context) (*model.User, error) + DeleteUser(c echo.Context) error +} + +type UserService struct { + DB *gorm.DB +} + +func (u *UserService) GetAllUsers(c echo.Context) ([]model.User, error) { + var users []model.User + + if err := u.DB.Omit("password").Find(&users).Error; err != nil { + return nil, err + } + + return users, nil +} + +func (u *UserService) GetUser(c echo.Context) (*model.User, error) { + var user *model.User + + userID := c.Param("uid") + + if err := u.DB.Omit("password").First(&user, userID).Error; err != nil { + return nil, err + } + + return user, nil +} + +func (u *UserService) CreateUser(c echo.Context) (*model.User, error) { + var user *model.User + + if err := validateData(c, &user); err != nil { + return nil, err + } + + user.CreatedAt = time.Now() + user.UpdatedAt = time.Now() + + if result := u.DB.Create(&user); result.Error != nil { + return nil, result.Error + } + + return user, nil +} + +func (u *UserService) UpdateUser(c echo.Context) (*model.User, error) { + var user *model.User + + userID := c.Param("uid") + + if err := u.DB.First(&user, userID).Error; err != nil { + return nil, err + } + + if err := c.Bind(&user); err != nil { + return nil, err + } + + u.DB.Save(&user) + + user.Password = "" + + return user, nil +} + +func (u *UserService) DeleteUser(c echo.Context) error { + var user model.User + userID := c.Param("uid") + + if err := u.DB.First(&user, userID).Error; err != nil { + return err + } + + u.DB.Delete(&user) + + return nil +} diff --git a/server/src/services/validator.go b/server/src/services/validator.go new file mode 100644 index 0000000..26344e1 --- /dev/null +++ b/server/src/services/validator.go @@ -0,0 +1,20 @@ +package services + +import ( + "github.com/go-playground/validator" + "github.com/labstack/echo/v4" +) + +// Validate the data sent to the server if the data is invalid, return an error otherwise, return nil +func validateData(c echo.Context, data interface{}) error { + if err := c.Bind(data); err != nil { + return err + } + + validator := validator.New() + if err := validator.Struct(data); err != nil { + return err + } + + return nil +} From f47ba3c04c4a19a8351cdf258dbfbf96180e844d Mon Sep 17 00:00:00 2001 From: David Oduneye Date: Wed, 1 Nov 2023 10:52:20 -0400 Subject: [PATCH 2/6] feat(server): implemented services, controller, route, etc. to improve code quality BREAKING CHANGE: --- client-new/App.tsx | 2 ++ client-new/package.json | 1 + client-new/yarn.lock | 28 ++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/client-new/App.tsx b/client-new/App.tsx index a662925..3380be2 100644 --- a/client-new/App.tsx +++ b/client-new/App.tsx @@ -5,6 +5,7 @@ import { NativeBaseProvider, extendTheme } from "native-base"; import { SafeAreaProvider } from "react-native-safe-area-context"; import { Auth0Provider } from "react-native-auth0"; import { AuthProvider } from "./src/contexts/AuthContext"; +import { getUser } from "./src/services/TestService"; export default function App() { const theme = extendTheme({ @@ -16,6 +17,7 @@ export default function App() { + getUser() diff --git a/client-new/package.json b/client-new/package.json index eecee96..e2f300b 100644 --- a/client-new/package.json +++ b/client-new/package.json @@ -16,6 +16,7 @@ "@types/react": "^18.2.28", "@types/react-dom": "^18.2.13", "@types/react-native": "^0.72.3", + "axios": "^1.6.0", "expo": "~49.0.13", "expo-dev-client": "^2.4.11", "expo-secure-store": "^12.5.0", diff --git a/client-new/yarn.lock b/client-new/yarn.lock index 4a13c17..49bc6c5 100644 --- a/client-new/yarn.lock +++ b/client-new/yarn.lock @@ -3557,6 +3557,15 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== +axios@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102" + integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + babel-core@^7.0.0-bridge.0: version "7.0.0-bridge.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" @@ -4910,6 +4919,11 @@ flow-parser@^0.206.0: resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.206.0.tgz#f4f794f8026535278393308e01ea72f31000bfef" integrity sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w== +follow-redirects@^1.15.0: + version "1.15.3" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a" + integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q== + fontfaceobserver@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz#5fb392116e75d5024b7ec8e4f2ce92106d1488c8" @@ -4924,6 +4938,15 @@ form-data@^3.0.1: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + freeport-async@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/freeport-async/-/freeport-async-2.0.0.tgz#6adf2ec0c629d11abff92836acd04b399135bab4" @@ -6970,6 +6993,11 @@ protobufjs@^7.2.4: "@types/node" ">=13.7.0" long "^5.0.0" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" From 2eb4b0aeb0edb499ab7a656fae8ed4051bec6c8b Mon Sep 17 00:00:00 2001 From: David Oduneye Date: Wed, 1 Nov 2023 10:55:10 -0400 Subject: [PATCH 3/6] style: formatting --- client-new/src/screens/app/HomeScreen.tsx | 2 +- server/README.md | 214 +++++++++++++++ server/data.sql | 105 -------- server/go.mod | 3 + server/go.sum | 6 + server/src/controller/aws.go | 247 ------------------ server/src/controller/persona.go | 127 --------- server/src/controller/setup.go | 96 ------- server/src/controller/subtask.go | 86 ------ server/src/controller/subtask_progress.go | 86 ------ server/src/controller/task.go | 98 ------- server/src/controller/task_progress.go | 86 ------ server/src/controller/user.go | 184 ------------- server/src/controller/user_profile.go | 170 ------------ server/src/controller/validator.go | 27 -- server/src/controller_new/user.go | 66 ----- server/src/controllers/file.go | 98 +++++++ server/src/controllers/persona.go | 93 +++++++ server/src/controllers/profile.go | 88 +++++++ server/src/controllers/subtask.go | 83 ++++++ server/src/controllers/task.go | 94 +++++++ server/src/controllers/user.go | 138 ++++++++++ server/src/database/db.go | 39 ++- server/src/main.go | 4 +- server/src/migrations/data.sql | 12 +- server/src/model/file.go | 12 - server/src/model/subtask_progress.go | 12 - server/src/model/task_progress.go | 12 - server/src/model/user.go | 15 -- server/src/models/file.go | 11 + server/src/{model => models}/persona.go | 8 +- .../user_profile.go => models/profile.go} | 12 +- server/src/{model => models}/subtask.go | 10 +- server/src/models/subtask_progress.go | 12 + server/src/{model => models}/task.go | 6 +- server/src/models/task_progress.go | 12 + server/src/models/user.go | 15 ++ server/src/routes/file.go | 18 ++ server/src/routes/persona.go | 20 ++ server/src/routes/profile.go | 18 ++ server/src/routes/subtask.go | 18 ++ server/src/routes/task.go | 19 ++ server/src/routes/user.go | 25 ++ server/src/services/file.go | 208 +++++++++++++++ server/src/services/persona.go | 91 +++++-- server/src/services/profile.go | 97 +++++++ server/src/services/subtask.go | 75 ++++++ server/src/services/task.go | 86 ++++++ server/src/services/user.go | 137 +++++++--- server/src/services/validator.go | 12 +- server/src/types/OnboardingResponse.go | 22 ++ server/tests/user_test.go | 42 +-- 52 files changed, 1708 insertions(+), 1569 deletions(-) delete mode 100644 server/data.sql delete mode 100644 server/src/controller/aws.go delete mode 100644 server/src/controller/persona.go delete mode 100644 server/src/controller/setup.go delete mode 100644 server/src/controller/subtask.go delete mode 100644 server/src/controller/subtask_progress.go delete mode 100644 server/src/controller/task.go delete mode 100644 server/src/controller/task_progress.go delete mode 100644 server/src/controller/user.go delete mode 100644 server/src/controller/user_profile.go delete mode 100644 server/src/controller/validator.go delete mode 100644 server/src/controller_new/user.go create mode 100644 server/src/controllers/file.go create mode 100644 server/src/controllers/persona.go create mode 100644 server/src/controllers/profile.go create mode 100644 server/src/controllers/subtask.go create mode 100644 server/src/controllers/task.go create mode 100644 server/src/controllers/user.go delete mode 100644 server/src/model/file.go delete mode 100644 server/src/model/subtask_progress.go delete mode 100644 server/src/model/task_progress.go delete mode 100644 server/src/model/user.go create mode 100644 server/src/models/file.go rename server/src/{model => models}/persona.go (58%) rename server/src/{model/user_profile.go => models/profile.go} (71%) rename server/src/{model => models}/subtask.go (51%) create mode 100644 server/src/models/subtask_progress.go rename server/src/{model => models}/task.go (78%) create mode 100644 server/src/models/task_progress.go create mode 100644 server/src/models/user.go create mode 100644 server/src/routes/file.go create mode 100644 server/src/routes/persona.go create mode 100644 server/src/routes/profile.go create mode 100644 server/src/routes/subtask.go create mode 100644 server/src/routes/task.go create mode 100644 server/src/routes/user.go create mode 100644 server/src/services/file.go create mode 100644 server/src/services/profile.go create mode 100644 server/src/services/subtask.go create mode 100644 server/src/services/task.go create mode 100644 server/src/types/OnboardingResponse.go diff --git a/client-new/src/screens/app/HomeScreen.tsx b/client-new/src/screens/app/HomeScreen.tsx index 92c3dca..cf6a6ab 100644 --- a/client-new/src/screens/app/HomeScreen.tsx +++ b/client-new/src/screens/app/HomeScreen.tsx @@ -8,7 +8,7 @@ import { } from "react-native-responsive-screen"; import LegacyWordmark from "../../components/reusable/LegacyWordmark"; import { SvgUri } from "react-native-svg"; -import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; +// import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { NavigationContainer } from '@react-navigation/native'; diff --git a/server/README.md b/server/README.md index 43db518..a6bf586 100644 --- a/server/README.md +++ b/server/README.md @@ -39,3 +39,217 @@ - [REST API Tutorial](https://restfulapi.net/) - [REST API Best Practices](https://www.freecodecamp.org/news/rest-api-best-practices-rest-endpoint-design-examples/) + + + +Certainly! Below is how you can organize the code into a Controller, Service, and Route, following the example you provided: + +### 1. **File Model** +The file model remains unchanged. + +```go +type File struct { +    gorm.Model +    FileName        string `gorm:"type:varchar(255)" json:"file_name" validate:"required"` +    FileDescription string `gorm:"type:text" json:"file_description" validate:"required"` +    FilePath        string `gorm:"type:varchar(255)" json:"file_path" validate:"required"` +    UserID          uint   `json:"user_id" validate:"required"` +    User            *User  `gorm:"foreignkey:UserID" json:"-"` +} +``` + +### 2. **File Service** +The service will handle the business logic related to files. + +```go +package services + +import ( +    "server/src/models" +    "gorm.io/gorm" +) + +type FileServiceInterface interface { +    CreateFile(file models.File, userID uint) error +    GetFile(fileID uint) (models.File, error) +    DeleteFile(fileID uint) error +    GetAllFiles(userID uint) ([]models.File, error) +    // Add more methods as needed +} + +type FileService struct { +    DB *gorm.DB +} + +// Implement the methods from FileServiceInterface +``` + +### 3. **File Controller** +The controller will handle HTTP requests and responses. + +```go +package controllers + +import ( +    "net/http" +    "server/src/services" +    "github.com/labstack/echo/v4" +) + +type FileController struct { +    fileService services.FileServiceInterface +} + +func NewFileController(fileService services.FileServiceInterface) *FileController { +    return &FileController{fileService: fileService} +} + +// Implement handlers such as CreateFile, GetFile, DeleteFile, etc. +``` + +### 4. **File Routes** +Define the routes for handling file-related requests. + +```go +func FileRoutes(g *echo.Group, fileService services.FileServiceInterface) { +    fileController := controllers.NewFileController(fileService) + +    g.POST("/", fileController.CreateFile) +    g.GET("/:fid", fileController.GetFile) +    g.DELETE("/:fid", fileController.DeleteFile) +    g.GET("/user/:uid", fileController.GetAllFiles) +    // Add more routes as needed +} +``` + +### 5. **Remaining AWS-specific functions** +You can consider creating a utility or helper package where you keep AWS-specific functionalities like `createAwsSession()`, or you could incorporate them into the service layer as private methods. + +### Conclusion +- **Model**: Structure representing the data. +- **Service**: Contains the business logic and interactions with the database. +- **Controller**: Handles HTTP requests, calling the appropriate services. +- **Routes**: Defines the HTTP routes and endpoints. + +You might also want to create a separate utility or helper for AWS-specific operations. This organization follows a clean architecture, separating concerns and making the codebase easier to manage and extend. Note that the actual implementation inside the methods (e.g., interactions with the database and AWS services) should be written based on your application's specific needs and logic. + +Certainly! Below is the detailed implementation of the handlers, methods for services, controllers, and utilities/helpers. + +### **Utilities/Helpers (AWS Specific Operations)** + +```go +package utils + +import ( +    "github.com/aws/aws-sdk-go/aws" +    "github.com/aws/aws-sdk-go/aws/credentials" +    "github.com/aws/aws-sdk-go/aws/session" +) + +func CreateAWSSession() (*session.Session, error) { +    sess, err := session.NewSession(&aws.Config{ +        Region:      aws.String("us-east-2"), +        Credentials: credentials.NewStaticCredentials("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY", ""), +    }) + +    return sess, err +} +``` + +### **File Service** + +```go +package services + +import ( +    "errors" +    "server/src/models" +    "gorm.io/gorm" +    // Import other necessary packages like AWS SDK +) + +type FileService struct { +    DB *gorm.DB +    // You can also inject the AWS utility here if necessary +} + +func (fs *FileService) CreateFile(file models.File) error { +    // Your code for creating a file goes here. This could involve: +    // - Validating the file +    // - Saving it to AWS S3 +    // - Saving file metadata to your database + +    return nil // or return an error if something goes wrong +} + +func (fs *FileService) GetFile(fileID uint) (models.File, error) { +    var file models.File + +    result := fs.DB.First(&file, fileID) +    if result.Error != nil { +        return file, errors.New("file not found") +    } + +    return file, nil +} + +// Implement other methods like DeleteFile, GetAllFiles, etc. +``` + +### **File Controller** + +```go +package controllers + +import ( +    "net/http" +    "server/src/services" +    "github.com/labstack/echo/v4" +) + +type FileController struct { +    fileService services.FileService +} + +func (fc *FileController) CreateFile(c echo.Context) error { +    // Your code for handling the creation of a file goes here. +    // This could involve: +    // - Receiving file data from a client +    // - Calling the fileService.CreateFile method + +    return c.JSON(http.StatusCreated, "File successfully created") +} + +func (fc *FileController) GetFile(c echo.Context) error { +    fileID := c.Param("fid") // getting file ID from the route parameter + +    file, err := fc.fileService.GetFile(fileID) +    if err != nil { +        return c.JSON(http.StatusNotFound, err.Error()) +    } + +    return c.JSON(http.StatusOK, file) +} + +// Implement other handlers like DeleteFile, GetAllFiles, etc. +``` + +### **Routes** + +```go +func FileRoutes(g *echo.Group, fileService services.FileService) { +    fileController := controllers.NewFileController(fileService) + +    g.POST("/", fileController.CreateFile) +    g.GET("/:fid", fileController.GetFile) +    // Define other routes like DELETE, PUT, etc. +} +``` + +### **Explanation** +- **Utilities/Helpers**: A utility function to create an AWS session. +- **Service**: Handles the business logic, interacts with the database and AWS. +- **Controller**: Receives HTTP requests, communicates with services, and returns HTTP responses. +- **Routes**: Defines the HTTP endpoints and connects them to the controller functions. + +Make sure to replace `"YOUR_ACCESS_KEY"` and `"YOUR_SECRET_KEY"` in the utility function with your actual AWS credentials. Additionally, you might need to customize the error handling, validation, and other business logic according to your specific use case and error handling strategy. \ No newline at end of file diff --git a/server/data.sql b/server/data.sql deleted file mode 100644 index 76dfd60..0000000 --- a/server/data.sql +++ /dev/null @@ -1,105 +0,0 @@ --- Creating test personas -INSERT INTO personas (persona_title, persona_description, created_at, updated_at) VALUES -('Procrastinating Rookie', 'Compassionate and reassuring', clock_timestamp(), clock_timestamp()), -('Adventurous Optimist', 'Informed and death positive', clock_timestamp(), clock_timestamp()), -('Adventurous Optimist with Wealth', 'Expert driven and death positive', clock_timestamp(), clock_timestamp()); - --- Creating test users -INSERT INTO users (username, password, email, persona_id, created_at, updated_at) VALUES -('testuser1', 'password', 'user1@example.com', 1, clock_timestamp(), clock_timestamp()), -('testuser2', 'password', 'user2@example.com', 2, clock_timestamp(), clock_timestamp()), -('testuser3', 'password', 'user3@example.com', 3, clock_timestamp(), clock_timestamp()), -('testuser4', 'password', 'user4@example.com', 1, clock_timestamp(), clock_timestamp()), -('testuser5', 'password', 'user5@example.com', 2, clock_timestamp(), clock_timestamp()); - --- Creating user profile -INSERT INTO user_profiles (name, user_id, date_of_birth, phone_number, created_at, updated_at) VALUES -('Test User 1', 1, '1990-01-01', '5555555555', clock_timestamp(), clock_timestamp()), -('Test User 2', 2, '1990-01-01', '5555555555', clock_timestamp(), clock_timestamp()), -('Test User 3', 3, '1990-01-01', '5555555555', clock_timestamp(), clock_timestamp()), -('Test User 4', 4, '1990-01-01', '5555555555', clock_timestamp(), clock_timestamp()), -('Test User 5', 5, '1990-01-01', '5555555555', clock_timestamp(), clock_timestamp()); - --- Creating test tasks -INSERT INTO tasks (task_name, task_description, created_at, updated_at) VALUES -('Acknowledging Fear', 'Acknowledge your aversion to end of life planning', clock_timestamp(), clock_timestamp()), -('Understanding EOLP', 'Create familiarity with the process', clock_timestamp(), clock_timestamp()), -('Values and Priorities', 'Define your values and priorities', clock_timestamp(), clock_timestamp()), -('Initial Plan', 'Create an initial end-of-life plan', clock_timestamp(), clock_timestamp()), -('Existing Financials', 'Review your existing financial plan', clock_timestamp(), clock_timestamp()), -('Non-financial Aspects', 'Explore non-financial aspects', clock_timestamp(), clock_timestamp()), -('Will', 'Create a comprehensive will', clock_timestamp(), clock_timestamp()), -('Specific Wishes', 'Communicate any specific wishes', clock_timestamp(), clock_timestamp()), -('Plan Moving Forward', 'Regularly review and update', clock_timestamp(), clock_timestamp()), -('Assemble Team', 'Assemble your financial team', clock_timestamp(), clock_timestamp()), -('Living Trust', 'Establish a revocable living trust', clock_timestamp(), clock_timestamp()), -('Tax Planning', 'Leverage tax planning strategies', clock_timestamp(), clock_timestamp()), -('Family Governance', 'Develop a family governance plan.', clock_timestamp(), clock_timestamp()), -('Emotional and Spiritual', 'Address emotional and spiritual concerns.', clock_timestamp(), clock_timestamp()), -('Create Project', 'Create a legacy project', clock_timestamp(), clock_timestamp()); - --- Creating test task progress -INSERT INTO task_progresses (user_id, task_id, completed) VALUES -(1, 1, True), -(1, 2, True), -(1, 3, False), -(1, 4, True); - - --- Creating test subtasks -INSERT INTO sub_tasks (task_id, task_name, task_description, created_at, updated_at) VALUES -(1, 'Research Fear', 'Research books, articles, or podcasts on overcoming fear of death.', clock_timestamp(), clock_timestamp()), -(1, 'Connect With Support', 'Connect with a local support group for individuals facing similar fears.', clock_timestamp(), clock_timestamp()), -(1, 'Manage Anxiety', 'Explore mindfulness or meditation practices to help manage anxiety related to end-of-life topics.', clock_timestamp(), clock_timestamp()), -(2, 'Create Checklist', 'Create a checklist of basic personal information needed for end-of-life planning.', clock_timestamp(), clock_timestamp()), -(3, 'Your Values', 'Write down your personal values and beliefs.', clock_timestamp(), clock_timestamp()), -(3, 'Causes to Support', 'Identify specific causes or charities you would like to support', clock_timestamp(), clock_timestamp()), -(3, 'Legacy Statement', 'Legacy statement or ethical will to pass on your values to loved ones.', clock_timestamp(), clock_timestamp()), -(4, 'Draft Intentions', 'Draft a simple letter of intent outlining your wishes for end-of-life care.', clock_timestamp(), clock_timestamp()), -(4, 'Legal Plans', 'Complete healthcare proxies and power of attorney agents.', clock_timestamp(), clock_timestamp()), -(5, 'Financial Inventory', 'Conduct a thorough inventory of all financial accounts and assets.', clock_timestamp(), clock_timestamp()), -(5, 'Life Insurance', 'Review and update your life insurance policies, including coverage amounts and beneficiaries.', clock_timestamp(), clock_timestamp()), -(5, 'Financial Document Storage', 'Store digital copies of important financial documents in a secure location.', clock_timestamp(), clock_timestamp()), -(6, 'Personal Values', 'Create a comprehensive list of your personal values, preferences', clock_timestamp(), clock_timestamp()), -(6, 'Important Contacts', 'Create a comprehensive list of important contacts.', clock_timestamp(), clock_timestamp()), -(6, 'Organ Donation', 'Document your preferred organ donation choices', clock_timestamp(), clock_timestamp()), -(6, 'Burial/Cremation', 'Document your preferred burial or cremation preferences.', clock_timestamp(), clock_timestamp()), -(6, 'Eulogy', 'Create a eulogy for yourself', clock_timestamp(), clock_timestamp()), -(7, 'Asset Distribution', 'Leverage draft specific clauses regarding asset distribution, including any conditional bequests.', clock_timestamp(), clock_timestamp()), -(7, 'Minor Children', 'Designate a guardian for minor children and establish trusts for their care.', clock_timestamp(), clock_timestamp()), -(7, 'Digital Assets', 'Include provisions for digital assets, such as passwords and access instructions.', clock_timestamp(), clock_timestamp()), -(8, 'Family Members', 'Schedule individual meetings with family members to discuss your end-of-life plans.', clock_timestamp(), clock_timestamp()), -(8, 'Financial Institutions', 'Provide your executor with a detailed list of your financial institutions, account numbers, and contact information.', clock_timestamp(), clock_timestamp()), -(8, 'Important Document Location', 'Share the location of your important documents, such as your will and healthcare directives.', clock_timestamp(), clock_timestamp()), -(9, 'Annual Reminder', 'Set up an automated annual reminder for financial plan reviews.', clock_timestamp(), clock_timestamp()), -(9, 'Major Life Change Updates', 'Update your beneficiaries and estate plan whenever you experience significant life changes, such as marriage, divorce, or the birth of a child.', clock_timestamp(), clock_timestamp()), -(9, 'Periodic Preference Reviews', 'Conduct periodic reviews of your funeral or memorial preferences and make adjustments as needed.', clock_timestamp(), clock_timestamp()), -(10, 'Find Lawyer', 'Research and interview multiple trust and estate lawyers to find the most suitable one.', clock_timestamp(), clock_timestamp()), -(10, 'Financial Planner', 'Hire a financial planner to create a detailed financial roadmap and investment strategy.', clock_timestamp(), clock_timestamp()), -(10, 'Certified Public Accountant', 'Collaborate with a certified public accountant (CPA) to address tax planning and compliance.', clock_timestamp(), clock_timestamp()), -(11, 'Comprehensive Trust Document', 'Consult with your trust and estate lawyer to draft a comprehensive trust document.', clock_timestamp(), clock_timestamp()), -(11, 'Asset Inventory', 'Review and update your asset inventory to ensure all valuable assets are included in the trust.', clock_timestamp(), clock_timestamp()), -(11, 'Backup Successor Trustees', 'Appoint backup successor trustees and provide them with necessary information.', clock_timestamp(), clock_timestamp()), -(12, 'Tax Planning Calendar', 'Create a comprehensive tax planning calendar outlining important deadlines.', clock_timestamp(), clock_timestamp()), -(12, 'Reducing Estate Tax Liability', 'Implement gifting strategies to reduce potential estate tax liability.', clock_timestamp(), clock_timestamp()), -(12, 'Charitable Giving', 'Consult with a philanthropic advisor to structure charitable giving in a tax-efficient manner.', clock_timestamp(), clock_timestamp()), -(15, 'Family Meetings', 'Schedule regular family meetings, including an annual retreat to discuss long-term objectives.', clock_timestamp(), clock_timestamp()), -(13, 'Family Counseling', 'Work with a family therapist or counselor to facilitate constructive communication and conflict resolution strategies.', clock_timestamp(), clock_timestamp()), -(13, 'Family Mission', 'Create a family mission statement or constitution outlining the family''s values, mission, and governance principles.', clock_timestamp(), clock_timestamp()), -(14, 'Death Doula', 'Arrange meetings with a death doula and spiritual advisor to explore emotional and spiritual concerns.', clock_timestamp(), clock_timestamp()), -(15, 'Life Story', 'Record your life story and personal anecdotes to pass on your legacy.', clock_timestamp(), clock_timestamp()), -(15, 'Family Philanthropic Participation', 'Establish a process for family members to participate in philanthropic initiatives and maintain alignment with family values.', clock_timestamp(), clock_timestamp()); - --- Insert relationships into the persona_tasks junction table - --- Persona 1: Procrastinating Rookie -INSERT INTO persona_tasks (persona_id, task_id) VALUES -(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (1, 7), (1, 8); - --- Persona 2: Adventurous Optimist -INSERT INTO persona_tasks (persona_id, task_id) VALUES -(2, 4), (2, 5), (2, 6), (2, 6), (2, 6), (2, 7), (2, 8), (2, 9), (2, 9), (2, 9), (2, 10), (2, 11), (2, 12), (2, 13), (2, 14), (2, 15); - --- Persona 3: Adventurous Optimist with Wealth -INSERT INTO persona_tasks (persona_id, task_id) VALUES -(3, 10), (3, 11), (3, 12), (3, 13), (3, 11), (3, 14), (3, 15), (3, 16), (3, 17), (3, 18), (3, 19), (3, 20), (3, 21), (3, 22), (3, 23), (3, 24), (3, 25), (3, 26), (3, 27), (3, 28); diff --git a/server/go.mod b/server/go.mod index dda552c..5a2f99f 100644 --- a/server/go.mod +++ b/server/go.mod @@ -9,6 +9,9 @@ require ( ) require ( + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/go-playground/validator/v10 v10.15.5 // indirect + github.com/joho/godotenv v1.5.1 // indirect github.com/radovskyb/watcher v1.0.7 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect ) diff --git a/server/go.sum b/server/go.sum index 2784419..2b54e6a 100644 --- a/server/go.sum +++ b/server/go.sum @@ -3,12 +3,16 @@ github.com/aws/aws-sdk-go v1.45.14/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8P github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp4Mit+3FDh548oRqwVgNsHA= github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig= +github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24= +github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= @@ -23,6 +27,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4= github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ= github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= diff --git a/server/src/controller/aws.go b/server/src/controller/aws.go deleted file mode 100644 index 4dce675..0000000 --- a/server/src/controller/aws.go +++ /dev/null @@ -1,247 +0,0 @@ -package controller - -import ( - "errors" - "fmt" - "io" - "net/http" - "server/src/model" - "strconv" - "time" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/credentials" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/s3" - "github.com/aws/aws-sdk-go/service/s3/s3manager" - "github.com/go-playground/validator" - - "github.com/labstack/echo/v4" - "gorm.io/gorm" -) - -type AwsController struct { - DB *gorm.DB -} - -func createAwsSession() (*session.Session, error) { - // TODO --> consider caching active session so we dont make a new one every time - sess, err := session.NewSession(&aws.Config{ - Region: aws.String("us-east-2"), - Credentials: credentials.NewStaticCredentials("AKIA2WVH6R5ZEMKYG7VW", "kOQ4kRX6UWbDjlW8MqItnrJgR2UrMRXgD4V2vend", ""), - }) - - if err != nil { - return nil, err - } - - return sess, nil -} - -func (a *AwsController) CreateFile(c echo.Context) error { - - var file model.File - - file.FileName = c.FormValue("file_name") - file.FileDescription = c.FormValue("file_description") - file.FilePath = c.FormValue("file_path") - user_id, err := strconv.ParseUint(c.FormValue("user_id"), 10, 0) - if err != nil { - return c.JSON(http.StatusBadRequest, err.Error()) - } - file.UserID = uint(user_id) - - var user model.User - a.DB.First(&user, uint(user_id)) - if user.ID == 0 { - return c.JSON(http.StatusNotFound, "User not found") - } - file.User = user - - // check if binded data is valid according to rules defined in model - validator := validator.New() - if err := validator.Struct(file); err != nil { - return c.JSON(http.StatusBadRequest, err.Error()) - } - - // check if file exists - var checkFile model.File - result := a.DB.Where("file_name = ?", file.FileName).Where("user_id = ?", file.UserID).First(&checkFile) - if result.Error == nil { - return c.JSON(http.StatusNotAcceptable, "Filename already exists") - } - - // get file and check that size < 5 MB - data, err := c.FormFile("file_data") - if err != nil { - return c.JSON(http.StatusBadRequest, err.Error()) - } - - fmt.Printf("%v", data.Size) - if data.Size > 5000000 { - return c.JSON(http.StatusBadRequest, "Maximum file size 5 MB") - } - - src, err := data.Open() - if err != nil { - return c.JSON(http.StatusBadRequest, err.Error()) - } - defer src.Close() - - // file info validated, now upload to s3 bucket - sess, err := createAwsSession() - if err != nil { - return c.JSON(http.StatusInternalServerError, err.Error()) - } - - // define upload parameters - uploader := s3manager.NewUploader(sess) - bucket := "generate-legacy-storage" - filename := fmt.Sprintf("%v-%v", file.UserID, file.FileName) - - // upload file - _, err = uploader.Upload(&s3manager.UploadInput{ - Bucket: aws.String(bucket), - Key: aws.String(filename), - Body: src, - }) - - if err != nil { - return c.JSON(http.StatusInternalServerError, err.Error()) - } - - // once file uploads successfully, update table in DB - a.DB.Create(&file) - - return c.JSON(http.StatusCreated, file) -} - -func (a *AwsController) GetFile(c echo.Context) error { - // attempt to locate file in DB - var dbFile model.File - fileID := c.Param("fid") - result := a.DB.First(&dbFile, fileID) - - // check if file exists - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return c.JSON(http.StatusNotFound, "File not found") - } - - // create session and service client - sess, err := createAwsSession() - if err != nil { - return c.JSON(http.StatusInternalServerError, err.Error()) - } - svc := s3.New(sess) - - // define parameters to get file - bucketName := "generate-legacy-storage" - key := fmt.Sprintf("%v-%v", dbFile.UserID, dbFile.FileName) - - // download file from s3 bucket - file, err := svc.GetObject(&s3.GetObjectInput{ - Bucket: aws.String(bucketName), - Key: aws.String(key), - }) - - if err != nil { - return c.JSON(http.StatusInternalServerError, err.Error()) - } - defer file.Body.Close() - - // configure response to send file - c.Response().Header().Set("Content-Type", "application/octet-stream") - c.Response().Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", key)) - - // stream s3 object body to HTTP response - _, err = io.Copy(c.Response().Writer, file.Body) - if err != nil { - return c.JSON(http.StatusInternalServerError, err.Error()) - } - - return nil -} - -func (a *AwsController) DeleteFile(c echo.Context) error { - // attempt to locate file in DB - var file model.File - fileID := c.Param("fid") - result := a.DB.First(&file, fileID) - - // check if file exists - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return c.JSON(http.StatusNotFound, "File not found") - } - - // create session and service client, then delete file - sess, err := createAwsSession() - if err != nil { - return c.JSON(http.StatusInternalServerError, err.Error()) - } - svc := s3.New(sess) - - bucketName := "generate-legacy-storage" - objectKey := fmt.Sprintf("%v-%v", file.UserID, file.FileName) - - _, err = svc.DeleteObject(&s3.DeleteObjectInput{ - Bucket: aws.String(bucketName), - Key: aws.String(objectKey), - }) - if err != nil { - return c.JSON(http.StatusInternalServerError, err.Error()) - } - - // delete file from DB after successful removal from AWS - a.DB.Delete(&file) - - return c.JSON(http.StatusOK, "File deleted") -} - -func (a *AwsController) GetPresignedURL(c echo.Context) error { - // attempt to locate file in DB - var file model.File - fileID := c.Param("fid") - result := a.DB.First(&file, fileID) - - // check if file exists - if errors.Is(result.Error, gorm.ErrRecordNotFound) { - return c.JSON(http.StatusNotFound, "File not found") - } - - // create session and service client, then create presigned url - sess, err := createAwsSession() - if err != nil { - return c.JSON(http.StatusInternalServerError, err.Error()) - } - svc := s3.New(sess) - - bucketName := "generate-legacy-storage" - objectKey := fmt.Sprintf("%v-%v", file.UserID, file.FileName) - - req, _ := svc.GetObjectRequest(&s3.GetObjectInput{ - Bucket: aws.String(bucketName), - Key: aws.String(objectKey), - }) - - // set URL expiration and get url - days, err := strconv.Atoi(c.Param("days")) - if err != nil { - return c.JSON(http.StatusBadRequest, "Invalid expiration time. Expecting integer days") - } - expiration := time.Duration(24*time.Hour) * time.Duration(days) - - url, err := req.Presign(expiration) - if err != nil { - return c.JSON(http.StatusInternalServerError, err.Error()) - } - - return c.JSON(http.StatusOK, url) -} - -func (a *AwsController) GetAllFiles(c echo.Context) error { - var files []model.File - userID := c.Param("uid") - - a.DB.Where("user_id = ?", userID).Find(&files) - return c.JSON(http.StatusOK, files) -} diff --git a/server/src/controller/persona.go b/server/src/controller/persona.go deleted file mode 100644 index 402d0ad..0000000 --- a/server/src/controller/persona.go +++ /dev/null @@ -1,127 +0,0 @@ -package controller - -import ( - "net/http" - "server/src/model" - - "github.com/go-playground/validator" - "github.com/labstack/echo/v4" - "gorm.io/gorm" -) - -type PersonaController struct { - DB *gorm.DB -} - -func (u *PersonaController) GetAllPersonas(c echo.Context) error { - var personas []model.Persona - - u.DB.Find(&personas) - return c.JSON(http.StatusOK, personas) -} - -func (u *PersonaController) GetPersona(c echo.Context) error { - var persona model.Persona - personaID := c.Param("pid") - - u.DB.First(&persona, personaID) - - if persona.ID == 0 { - return c.JSON(http.StatusNotFound, "Persona not found") - } - - return c.JSON(http.StatusOK, persona) -} - -func (u *PersonaController) CreatePersona(c echo.Context) error { - var persona model.Persona - - if err := c.Bind(&persona); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - validator := validator.New() - - if err := validator.Struct(persona); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - u.DB.Create(&persona) - - return c.JSON(http.StatusCreated, persona) -} - -func (u *PersonaController) UpdatePersona(c echo.Context) error { - var persona model.Persona - personaID := c.Param("pid") - - u.DB.First(&persona, personaID) - - if persona.ID == 0 { - return c.JSON(http.StatusNotFound, "Persona not found") - } - - if err := c.Bind(&persona); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - u.DB.Save(&persona) - - return c.JSON(http.StatusOK, persona) -} - -func (u *PersonaController) DeletePersona(c echo.Context) error { - var persona model.Persona - personaID := c.Param("pid") - - u.DB.First(&persona, personaID) - - if persona.ID == 0 { - return c.JSON(http.StatusNotFound, "Persona not found") - } - - u.DB.Delete(&persona) - - return c.JSON(http.StatusOK, "Persona deleted") -} - -func (u *PersonaController) AddTasksToPersona(c echo.Context) error { - var persona model.Persona - personaID := c.Param("pid") - - u.DB.First(&persona, personaID) - - if persona.ID == 0 { - return c.JSON(http.StatusNotFound, "Persona not found") - } - - var taskIDs []uint - if err := c.Bind(&taskIDs); err != nil { - return c.JSON(http.StatusBadRequest, "Invalid request body") - } - - var tasks []model.Task - if err := u.DB.Find(&tasks, taskIDs).Error; err != nil { - return c.JSON(http.StatusNotFound, "One or more tasks not found") - } - - u.DB.Model(&persona).Association("Tasks").Append(tasks) - u.DB.Save(&persona) - - return c.JSON(http.StatusOK, persona) -} - -func (u *PersonaController) GetPersonaTasks(c echo.Context) error { - var persona model.Persona - personaID := c.Param("pid") - - if err := u.DB.First(&persona, personaID).Error; err != nil { - return c.JSON(http.StatusNotFound, "Persona not found") - } - - // Retrieve tasks related to the persona - var tasks []model.Task - u.DB.Model(&persona).Association("Tasks").Find(&tasks) - - return c.JSON(http.StatusOK, tasks) -} diff --git a/server/src/controller/setup.go b/server/src/controller/setup.go deleted file mode 100644 index 45a5089..0000000 --- a/server/src/controller/setup.go +++ /dev/null @@ -1,96 +0,0 @@ -package controller - -import ( - "github.com/labstack/echo/v4" - "gorm.io/gorm" -) - -func SetupControllers(e *echo.Echo, db *gorm.DB) { - // Create a new instance of the controller with the database connection - userController := UserController{db} - personaController := PersonaController{db} - - userProfileController := UserProfileController{db} - taskController := TaskController{db} - subtaskController := SubtaskController{db} - taskprogressController := TaskProgressController{db} - subtaskprogressController := SubTaskProgressController{db} - - awsController := AwsController{db} - - // User routes - e.GET("api/users", userController.GetAllUsers) - e.GET("api/users/:uid", userController.GetUser) - e.GET("api/users/username/:username", userController.GetUserFromUsername) - e.GET("api/users/firebase/:firebaseid", userController.GetUserFromFirebaseID) - - // Once user gets created call this functon X - // e.POST("api/progress/:uid", taskprogressController.CreateAllTaskProgress) - // User has 4 tasks -> (User 1, Task 1), (User 1, Task 2), (User 1, Task 3), (User 1, Task 4) - // e.POST("api/subprogress/:uid", subtaskprogressController.CreateAllSubTaskProgress) - - e.GET("api/users/:uid/persona", userController.GetUserPersona) - e.GET("api/users/:uid/tasks", userController.GetUserTasks) - e.GET("api/users/:uid/profile", userController.GetUserProfile) - - e.POST("api/users", userController.CreateUser) - e.PUT("api/users/:uid", userController.UpdateUser) - e.DELETE("api/users/:uid", userController.DeleteUser) - - // Persona routes - e.GET("api/personas", personaController.GetAllPersonas) - e.GET("api/personas/:pid", personaController.GetPersona) - - // Get a persona tasks - e.GET("api/personas/:pid/tasks", personaController.GetPersonaTasks) - - e.POST("api/personas/", personaController.CreatePersona) - e.PUT("api/personas/:pid", personaController.UpdatePersona) - e.DELETE("api/personas/:pid", personaController.DeletePersona) - e.PUT("api/personas/:pid/tasks", personaController.AddTasksToPersona) - - // User Profile routes - e.GET("api/profiles/:upid", userProfileController.GetUserProfile) - e.POST("api/profiles/:uid/", userProfileController.CreateUserProfile) // Creates a user profile for the given user - e.PUT("api/profiles/:upid", userProfileController.UpdateUserProfile) - e.PUT("api/profiles/response/:uid", userProfileController.CreateOnboardingResponse) - e.DELETE("api/profiles/:upid", userProfileController.DeleteUserProfile) - - // Task routes - e.GET("api/tasks", taskController.GetAllTasks) - e.GET("api/tasks/:tid", taskController.GetTask) - e.POST("api/tasks", taskController.CreateTask) - e.PUT("api/tasks/:tid", taskController.UpdateTask) - e.DELETE("api/tasks/:tid", taskController.DeleteTask) - e.GET("api/tasks/:tid/subtasks", taskController.GetSubtasksFromTask) - - // SubTask routes - e.GET("api/subtasks", subtaskController.GetAllSubtasks) - e.GET("api/subtasks/:id", subtaskController.GetAllSubtasks) - e.POST("api/subtasks", subtaskController.CreateSubtask) - e.PUT("api/subtasks/:id", subtaskController.UpdateSubtask) - e.DELETE("api/subtasks/:id", subtaskController.DeleteSubtask) - - // Task Progress routes - e.GET("api/progress", taskprogressController.GetAllTaskProgress) - e.GET("api/progress/:id", taskprogressController.GetTaskProgress) - - e.PUT("api/progress/:id", taskprogressController.UpdateTaskProgress) - e.DELETE("api/progress/:id", taskprogressController.DeleteTaskProgress) - - // Subtask Progress routes - e.GET("api/subprogress", subtaskprogressController.GetAllSubTaskProgress) - e.GET("api/subprogress/:id", subtaskprogressController.GetSubTaskProgress) - e.PUT("api/subprogress/:id", subtaskprogressController.UpdateSubTaskProgress) - e.DELETE("api/subprogress/:id", subtaskprogressController.DeleteSubTaskProgress) - - // - Get all files (file names and tags and id getting the actual file is seperate) for a user. - // - Auth-related routes (login, logout). - - // AWS - e.GET("/api/aws/:fid", awsController.GetFile) - e.POST("/api/aws", awsController.CreateFile) - e.DELETE("/api/aws/:fid", awsController.DeleteFile) - e.GET("/api/aws/:fid/:days", awsController.GetPresignedURL) - e.GET("/api/aws/user/:uid", awsController.GetAllFiles) -} diff --git a/server/src/controller/subtask.go b/server/src/controller/subtask.go deleted file mode 100644 index 9015f51..0000000 --- a/server/src/controller/subtask.go +++ /dev/null @@ -1,86 +0,0 @@ -package controller - -import ( - "net/http" - "server/src/model" - - "github.com/go-playground/validator" - "github.com/labstack/echo/v4" - "gorm.io/gorm" -) - -type SubtaskController struct { - DB *gorm.DB -} - -func (s *SubtaskController) GetAllSubtasks(c echo.Context) error { - var subtasks []model.SubTask - - s.DB.Find(&subtasks) - return c.JSON(http.StatusOK, subtasks) -} - -func (s *SubtaskController) GetSubtask(c echo.Context) error { - var subtask model.SubTask - subtaskID := c.Param("id") - - s.DB.First(&subtask, subtaskID) - - if subtask.ID == 0 { - return c.JSON(http.StatusNotFound, "Subtask not found") - } - - return c.JSON(http.StatusOK, subtask) -} - -func (s *SubtaskController) CreateSubtask(c echo.Context) error { - var subtask model.SubTask - - if err := c.Bind(&subtask); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - validator := validator.New() - - if err := validator.Struct(subtask); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - s.DB.Create(&subtask) - - return c.JSON(http.StatusCreated, subtask) -} - -func (s *SubtaskController) UpdateSubtask(c echo.Context) error { - var subtask model.SubTask - subtaskID := c.Param("id") - - s.DB.First(&subtask, subtaskID) - - if subtask.ID == 0 { - return c.JSON(http.StatusNotFound, "Subtask not found") - } - - if err := c.Bind(&subtask); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - s.DB.Save(&subtask) - - return c.JSON(http.StatusOK, subtask) -} - -func (s *SubtaskController) DeleteSubtask(c echo.Context) error { - var subtask model.SubTask - subtaskID := c.Param("id") - - s.DB.First(&subtask, subtaskID) - - if subtask.ID == 0 { - return c.JSON(http.StatusNotFound, "Subtask not found") - } - - s.DB.Delete(&subtask) - - return c.JSON(http.StatusOK, "Subtask deleted") -} diff --git a/server/src/controller/subtask_progress.go b/server/src/controller/subtask_progress.go deleted file mode 100644 index bf66ded..0000000 --- a/server/src/controller/subtask_progress.go +++ /dev/null @@ -1,86 +0,0 @@ -package controller - -import ( - "net/http" - "server/src/model" - - "github.com/go-playground/validator" - "github.com/labstack/echo/v4" - "gorm.io/gorm" -) - -type SubTaskProgressController struct { - DB *gorm.DB -} - -func (s *SubTaskProgressController) GetAllSubTaskProgress(c echo.Context) error { - var progress []model.SubTaskProgress - - s.DB.Find(&progress) - return c.JSON(http.StatusOK, progress) -} - -func (s *SubTaskProgressController) GetSubTaskProgress(c echo.Context) error { - var progress model.SubTaskProgress - progressID := c.Param("id") - - s.DB.First(&progress, progressID) - - if progress.ID == 0 { - return c.JSON(http.StatusNotFound, "Progress not found") - } - - return c.JSON(http.StatusOK, progress) -} - -func (s *SubTaskProgressController) CreateSubTaskProgress(c echo.Context) error { - var progress model.SubTaskProgress - - if err := c.Bind(&progress); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - validator := validator.New() - - if err := validator.Struct(progress); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - s.DB.Create(&progress) - - return c.JSON(http.StatusCreated, progress) -} - -func (s *SubTaskProgressController) UpdateSubTaskProgress(c echo.Context) error { - var progress model.SubTaskProgress - progressID := c.Param("id") - - s.DB.First(&progress, progressID) - - if progress.ID == 0 { - return c.JSON(http.StatusNotFound, "Progress not found") - } - - if err := c.Bind(&progress); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - s.DB.Save(&progress) - - return c.JSON(http.StatusOK, progress) -} - -func (s *SubTaskProgressController) DeleteSubTaskProgress(c echo.Context) error { - var progress model.SubTaskProgress - progressID := c.Param("id") - - s.DB.First(&progress, progressID) - - if progress.ID == 0 { - return c.JSON(http.StatusNotFound, "Progress not found") - } - - s.DB.Delete(&progress) - - return c.JSON(http.StatusOK, "Progress deleted") -} diff --git a/server/src/controller/task.go b/server/src/controller/task.go deleted file mode 100644 index 2081232..0000000 --- a/server/src/controller/task.go +++ /dev/null @@ -1,98 +0,0 @@ -package controller - -import ( - "net/http" - "server/src/model" - - "github.com/go-playground/validator" - "github.com/labstack/echo/v4" - "gorm.io/gorm" -) - -type TaskController struct { - DB *gorm.DB -} - -func (t *TaskController) GetAllTasks(c echo.Context) error { - var task []model.Task - - t.DB.Find(&task) - return c.JSON(http.StatusOK, task) -} - -func (t *TaskController) GetTask(c echo.Context) error { - var task model.Task - taskID := c.Param("tid") - - t.DB.First(&task, taskID) - - if task.ID == 0 { - return c.JSON(http.StatusNotFound, "Task not found") - } - - return c.JSON(http.StatusOK, task) -} - -func (t *TaskController) CreateTask(c echo.Context) error { - var task model.Task - - if err := c.Bind(&task); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - validator := validator.New() - - if err := validator.Struct(task); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - t.DB.Create(&task) - - return c.JSON(http.StatusCreated, task) -} - -func (t *TaskController) UpdateTask(c echo.Context) error { - var task model.Task - taskID := c.Param("tid") - - t.DB.First(&task, taskID) - - if task.ID == 0 { - return c.JSON(http.StatusNotFound, "Task not found") - } - - if err := c.Bind(&task); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - t.DB.Save(&task) - - return c.JSON(http.StatusOK, task) -} - -func (t *TaskController) DeleteTask(c echo.Context) error { - var task model.Task - taskID := c.Param("tid") - - t.DB.First(&task, taskID) - - if task.ID == 0 { - return c.JSON(http.StatusNotFound, "Task not found") - } - - t.DB.Delete(&task) - - return c.JSON(http.StatusOK, "Task deleted") -} - -func (t *TaskController) GetSubtasksFromTask(c echo.Context) error { - taskID := c.Param("tid") - - // Retrieve the subtasks related to the task by ID - var subtasks []model.SubTask - if err := t.DB.Where("task_id = ?", taskID).Find(&subtasks).Error; err != nil { - return c.JSON(http.StatusNotFound, "Subtasks not found") - } - - return c.JSON(http.StatusOK, subtasks) -} diff --git a/server/src/controller/task_progress.go b/server/src/controller/task_progress.go deleted file mode 100644 index 4f9a98e..0000000 --- a/server/src/controller/task_progress.go +++ /dev/null @@ -1,86 +0,0 @@ -package controller - -import ( - "net/http" - "server/src/model" - - "github.com/go-playground/validator" - "github.com/labstack/echo/v4" - "gorm.io/gorm" -) - -type TaskProgressController struct { - DB *gorm.DB -} - -func (t *TaskProgressController) GetAllTaskProgress(c echo.Context) error { - var progress []model.TaskProgress - - t.DB.Find(&progress) - return c.JSON(http.StatusOK, progress) -} - -func (t *TaskProgressController) GetTaskProgress(c echo.Context) error { - var progress model.TaskProgress - progressID := c.Param("id") - - t.DB.First(&progress, progressID) - - if progress.ID == 0 { - return c.JSON(http.StatusNotFound, "Progress not found") - } - - return c.JSON(http.StatusOK, progress) -} - -func (t *TaskProgressController) CreateTaskProgress(c echo.Context) error { - var progress model.TaskProgress - - if err := c.Bind(&progress); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - validator := validator.New() - - if err := validator.Struct(progress); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - t.DB.Create(&progress) - - return c.JSON(http.StatusCreated, progress) -} - -func (t *TaskProgressController) UpdateTaskProgress(c echo.Context) error { - var progress model.TaskProgress - progressID := c.Param("id") - - t.DB.First(&progress, progressID) - - if progress.ID == 0 { - return c.JSON(http.StatusNotFound, "Progress not found") - } - - if err := c.Bind(&progress); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - t.DB.Save(&progress) - - return c.JSON(http.StatusOK, progress) -} - -func (t *TaskProgressController) DeleteTaskProgress(c echo.Context) error { - var progress model.TaskProgress - progressID := c.Param("id") - - t.DB.First(&progress, progressID) - - if progress.ID == 0 { - return c.JSON(http.StatusNotFound, "Progress not found") - } - - t.DB.Delete(&progress) - - return c.JSON(http.StatusOK, "Progress deleted") -} diff --git a/server/src/controller/user.go b/server/src/controller/user.go deleted file mode 100644 index 46208fd..0000000 --- a/server/src/controller/user.go +++ /dev/null @@ -1,184 +0,0 @@ -package controller - -import ( - "fmt" - "net/http" - "server/src/model" - - "github.com/go-playground/validator" - "github.com/labstack/echo/v4" - "gorm.io/gorm" -) - -type UserController struct { - DB *gorm.DB -} - -func (u *UserController) GetAllUsers(c echo.Context) error { - var users []model.User - - u.DB.Find(&users) - return c.JSON(http.StatusOK, users) -} - -func (u *UserController) GetUser(c echo.Context) error { - var user model.User - userID := c.Param("id") - - u.DB.First(&user, userID) - - if user.ID == 0 { - return c.JSON(http.StatusNotFound, "User not found") - } - - return c.JSON(http.StatusOK, user) -} - -func (u *UserController) GetUserPersona(c echo.Context) error { - var user model.User - var persona model.Persona - userID := c.Param("id") - - err := u.DB.First(&user, userID).Error - if err != nil { - return c.JSON(http.StatusNotFound, "User not found") - } - - u.DB.Model(&user).Association("Persona").Find(&persona) - if persona.ID == 0 { - return c.JSON(http.StatusNotFound, "User does not have a persona") - } - - return c.JSON(http.StatusOK, persona) -} - -func (u *UserController) GetUserTasks(c echo.Context) error { - // User -> Persona -> Tasks - var user model.User - var persona model.Persona - var tasks []model.Task - userID := c.Param("uid") - - err := u.DB.First(&user, userID).Error - if err != nil { - return c.JSON(http.StatusNotFound, "User not found") - } - u.DB.Model(&user).Association("Persona").Find(&persona) - if persona.ID == 0 { - return c.JSON(http.StatusNotFound, "User does not have a persona") - } - u.DB.Model(&persona).Association("Tasks").Find(&tasks) - if len(tasks) == 0 { - return c.JSON(http.StatusNotFound, "Persona does not have any tasks") - } - - return c.JSON(http.StatusOK, tasks) -} - -func (u *UserController) GetUserProfile(c echo.Context) error { - var user model.User - var userProfile model.UserProfile - userID := c.Param("uid") - - err := u.DB.First(&user, userID).Error - if err != nil { - return c.JSON(http.StatusNotFound, "User not found") - } - - err = u.DB.Where("user_id = ?", user.ID).First(&userProfile).Error - if err != nil { - return c.JSON(http.StatusNotFound, "User does not have a profile") - } - - return c.JSON(http.StatusOK, userProfile) -} - -func (u *UserController) GetUserFromUsername(c echo.Context) error { - username := c.Param("username") // Extract username from the query parameter - var user model.User - err := u.DB.Model(&user).Where("username = ?", username).First(&user).Error - if err != nil { - return c.JSON(http.StatusNotFound, "User not found") - } - - return c.JSON(http.StatusOK, user) -} - -func (u *UserController) GetUserFromFirebaseID(c echo.Context) error { - var user model.User - fib := c.Param("firebaseid") - - u.DB.Where("firebase_id = ?", fib).First(&user) - - if user.ID == 0 { - return c.JSON(http.StatusNotFound, "User not found or does not havea firebase id") - } - - return c.JSON(http.StatusOK, user) -} - -// TODO: Should create a user profile when a user is created -func (u *UserController) CreateUser(c echo.Context) error { - var user model.User - - fmt.Println("Creating user", user) - - // Bind the data sent in the POST request to the user model - // Handle the error if there is one - if err := c.Bind(&user); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - // Like Zod https://zod.dev/ - // https://pkg.go.dev/github.com/go-playground/validator/v10 - validator := validator.New() - - // Checks if the binded data is valid according to the rules defined in the model - if err := validator.Struct(user); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - err := u.DB.Create(&user).Error - if err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - return c.JSON(http.StatusCreated, user) -} - -func (u *UserController) UpdateUser(c echo.Context) error { - var user model.User - userID := c.Param("id") - - // Finds the user with the given ID - u.DB.First(&user, userID) - - // If the user is not found - if user.ID == 0 { - return c.JSON(http.StatusNotFound, "User not found") - } - - // Binds the data sent in the PUT request to the user model - if err := c.Bind(&user); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - u.DB.Save(&user) - - return c.JSON(http.StatusOK, user) -} - -func (u *UserController) DeleteUser(c echo.Context) error { - var user model.User - userID := c.Param("id") - - u.DB.First(&user, userID) - - if user.ID == 0 { - return c.JSON(http.StatusNotFound, "User not found") - } - - u.DB.Delete(&user) - - return c.JSON(http.StatusOK, "User deleted") -} diff --git a/server/src/controller/user_profile.go b/server/src/controller/user_profile.go deleted file mode 100644 index 92c270f..0000000 --- a/server/src/controller/user_profile.go +++ /dev/null @@ -1,170 +0,0 @@ -package controller - -import ( - "encoding/json" - "net/http" - "server/src/model" - - "github.com/go-playground/validator" - "github.com/labstack/echo/v4" - "gorm.io/gorm" -) - -type UserProfileController struct { - DB *gorm.DB -} - -func (up *UserProfileController) GetUserProfile(c echo.Context) error { - var userprofile model.UserProfile - userprofileID := c.Param("upid") - - up.DB.First(&userprofile, userprofileID) - - if userprofile.ID == 0 { - return c.JSON(http.StatusNotFound, "User Profile not found") - } - - return c.JSON(http.StatusOK, userprofile) -} - -func (up *UserProfileController) CreateUserProfile(c echo.Context) error { - var user model.User - userID := c.Param("uid") - - // Check if the user exists - err := up.DB.First(&user, userID).Error - if err != nil { - return c.JSON(http.StatusNotFound, "User not found") - } - - // Check if a user profile already exists for the user - var existingProfile model.UserProfile - err = up.DB.Where("user_id = ?", user.ID).First(&existingProfile).Error - if err == nil { - return c.JSON(http.StatusConflict, "User profile already exists") - } - - var userProfile model.UserProfile - if err := c.Bind(&userProfile); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - // Associate the profile with the user - userProfile.UserID = user.ID - - // Validate the user profile data before creating - validator := validator.New() - if err := validator.Struct(userProfile); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - // Create the user profile - result := up.DB.Create(&userProfile) - if result.Error != nil { - return handleError(c, http.StatusBadRequest, result.Error.Error()) - } - - return c.JSON(http.StatusCreated, userProfile) -} - -func (up *UserProfileController) UpdateUserProfile(c echo.Context) error { - var userprofile model.UserProfile - userprofileID := c.Param("upid") - - up.DB.First(&userprofile, userprofileID) - - if userprofile.ID == 0 { - return c.JSON(http.StatusNotFound, "User Profile not found") - } - - if err := validateData(c, &userprofile); err != nil { - return err - } - - up.DB.Save(&userprofile) - - return c.JSON(http.StatusOK, userprofile) -} - -type OnboardingResponse struct { - WorldviewQ1 string `json:"worldviewQ1"` - WorldviewQ2 string `json:"worldviewQ2"` - WorldviewQ3 string `json:"worldviewQ3"` - WorldviewQ4 string `json:"worldviewQ4"` - WorldviewQ5 string `json:"worldviewQ5"` - WorldviewQ6 string `json:"worldviewQ6"` - EmotionalPatternQ1 string `json:"emotionalPatternQ1"` - EmotionalPatternQ2 string `json:"emotionalPatternQ2"` - EmotionalPatternQ3 string `json:"emotionalPatternQ3"` - WorkstyleQ1 string `json:"workstyleQ1"` - WorkstyleQ2 string `json:"workstyleQ2"` - WorkstyleQ3 string `json:"workstyleQ3"` - WorkstyleQ4 string `json:"workstyleQ4"` - SocialInclinationQ1 string `json:"socialInclinationQ1"` - SocialInclinationQ2 string `json:"socialInclinationQ2"` - SocialInclinationQ3 string `json:"socialInclinationQ3"` - FunnelActivitiesQ1 string `json:"funnelActivitiesQ1"` - FunnelActivitiesQ2 string `json:"funnelActivitiesQ2"` -} - -func (up *UserProfileController) CreateOnboardingResponse(c echo.Context) error { - var user model.User - var onboardingResponse OnboardingResponse - var response []byte - userID := c.Param("uid") - - // Check if the user exists - err := up.DB.First(&user, userID).Error - if err != nil { - return c.JSON(http.StatusNotFound, "User not found") - } - - // Check if a user profile already exists for the user - var existingProfile model.UserProfile - err = up.DB.Where("user_id = ?", user.ID).First(&existingProfile).Error - if err != nil { - return c.JSON(http.StatusNotFound, "User profile not found") - } - - if err := c.Bind(&onboardingResponse); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - // Associate the profile with the user - response, err = json.Marshal(onboardingResponse) - if err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - existingProfile.OnboardingResponse = string(response) - - // Validate the user profile data before creating - validator := validator.New() - - if err := validator.Struct(existingProfile); err != nil { - return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()}) - } - - // Create the user profile - result := up.DB.Save(&existingProfile) - if result.Error != nil { - return handleError(c, http.StatusBadRequest, result.Error.Error()) - } - - return c.JSON(http.StatusCreated, existingProfile) -} - -func (up *UserProfileController) DeleteUserProfile(c echo.Context) error { - var userprofile model.UserProfile - userprofileID := c.Param("upid") - - up.DB.First(&userprofile, userprofileID) - - if userprofile.ID == 0 { - return c.JSON(http.StatusNotFound, "User Profile not found") - } - - up.DB.Delete(&userprofile) - - return c.JSON(http.StatusOK, "User Profile deleted") -} diff --git a/server/src/controller/validator.go b/server/src/controller/validator.go deleted file mode 100644 index 06a9fe6..0000000 --- a/server/src/controller/validator.go +++ /dev/null @@ -1,27 +0,0 @@ -package controller - -import ( - "net/http" - - "github.com/go-playground/validator" - "github.com/labstack/echo/v4" -) - -// Handle an error by returning a JSON response with the error message -func handleError(c echo.Context, status int, message string) error { - return c.JSON(status, map[string]string{"error": message}) -} - -// Validate the data sent to the server if the data is invalid, return an error otherwise, return nil -func validateData(c echo.Context, data interface{}) error { - if err := c.Bind(data); err != nil { - return handleError(c, http.StatusBadRequest, err.Error()) - } - - validator := validator.New() - if err := validator.Struct(data); err != nil { - return handleError(c, http.StatusBadRequest, err.Error()) - } - - return nil -} diff --git a/server/src/controller_new/user.go b/server/src/controller_new/user.go deleted file mode 100644 index 41aa4c7..0000000 --- a/server/src/controller_new/user.go +++ /dev/null @@ -1,66 +0,0 @@ -package controller_new - -import ( - "net/http" - "server/src/services" - - "github.com/labstack/echo/v4" -) - -type UserController struct { - userService *services.UserService -} - -func NewUserController(userService services.UserService) *UserController { - return &UserController{&userService} -} - -func (u *UserController) GetAllUsers(c echo.Context) error { - users, err := u.userService.GetAllUsers(c) - - if err != nil { - return c.JSON(http.StatusNotFound, "Failed to fetch users") - } - - return c.JSON(http.StatusOK, users) -} - -func (u *UserController) GetUser(c echo.Context) error { - user, err := u.userService.GetUser(c) - - if err != nil { - return c.JSON(http.StatusNotFound, "Failed to fetch user") - } - - return c.JSON(http.StatusOK, user) -} - -func (u *UserController) CreateUser(c echo.Context) error { - user, err := u.userService.CreateUser(c) - - if err != nil { - return c.JSON(http.StatusNotFound, "Failed to create user") - } - - return c.JSON(http.StatusCreated, user) -} - -func (u *UserController) UpdateUser(c echo.Context) error { - user, err := u.userService.UpdateUser(c) - - if err != nil { - return c.JSON(http.StatusNotFound, "Failed to update user") - } - - return c.JSON(http.StatusOK, user) -} - -func (u *UserController) DeleteUser(c echo.Context) error { - err := u.userService.DeleteUser(c) - - if err != nil { - return c.JSON(http.StatusNotFound, "Failed to update user") - } - - return c.JSON(http.StatusOK, "User deleted") -} diff --git a/server/src/controllers/file.go b/server/src/controllers/file.go new file mode 100644 index 0000000..488ab93 --- /dev/null +++ b/server/src/controllers/file.go @@ -0,0 +1,98 @@ +package controllers + +import ( + "fmt" + "net/http" + "server/src/models" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +type FileController struct { + fileService services.FileServiceInterface +} + +func NewFileController(fileService services.FileServiceInterface) *FileController { + return &FileController{fileService: fileService} +} + +func (f *FileController) GetAllUserFiles(c echo.Context) error { + userID := c.Param("uid") + file, err := f.fileService.GetAllUserFiles(userID) + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch files") + } + + return c.JSON(http.StatusOK, file) +} + +func (f *FileController) GetFileObject(c echo.Context) error { + fileID := c.Param("fid") + + file, fileName, err := f.fileService.GetFileObject(fileID) + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch file") + } + + key := fmt.Sprintf("%v-%v", fileID, fileName) + + contentDisposition := fmt.Sprintf("attachment; filename=%s", key) + + c.Response().Header().Set("Content-Type", "application/octet-stream") + c.Response().Header().Set("Content-Disposition", contentDisposition) + + return c.Blob(http.StatusOK, "application/octet-stream", file) +} + +func (f *FileController) GetPresignedURL(c echo.Context) error { + fileID := c.Param("fid") + days := c.QueryParam("days") + + if days == "" { + days = "1" + } + + url, err := f.fileService.GetPresignedURL(fileID, days) + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to get presigned url") + } + + return c.JSON(http.StatusOK, url) +} + +func (f *FileController) CreateFile(c echo.Context) error { + var file models.File + + if err := c.Bind(&file); err != nil { + return err + } + + if err := services.ValidateData(c, file); err != nil { + return c.JSON(http.StatusBadRequest, "Failed to validate the data"+err.Error()) + } + + form, err := c.MultipartForm() + if err != nil { + return c.JSON(http.StatusBadRequest, "Failed to get form") + } + + fileResponse := form.File["file_data"][0] + + file, err = f.fileService.CreateFile(file, fileResponse) + if err != nil { + return c.JSON(http.StatusNotFound, err) + } + + return c.JSON(http.StatusOK, file) +} + +func (f *FileController) DeleteFile(c echo.Context) error { + fileID := c.Param("fid") + + if err := f.fileService.DeleteFile(fileID); err != nil { + return c.JSON(http.StatusNotFound, "Failed to delete file") + } + + return c.JSON(http.StatusOK, "File deleted") +} diff --git a/server/src/controllers/persona.go b/server/src/controllers/persona.go new file mode 100644 index 0000000..eacf96b --- /dev/null +++ b/server/src/controllers/persona.go @@ -0,0 +1,93 @@ +package controllers + +import ( + "net/http" + "server/src/models" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +type PersonaController struct { + personaService services.PersonaServiceInterface +} + +func NewPersonaController(personaService services.PersonaServiceInterface) *PersonaController { + return &PersonaController{personaService: personaService} +} + +func (p *PersonaController) GetAllPersonas(c echo.Context) error { + personas, err := p.personaService.GetAllPersonas() + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch personas") + } + + return c.JSON(http.StatusOK, personas) +} + +func (p *PersonaController) GetPersona(c echo.Context) error { + personaID := c.Param("pid") + persona, err := p.personaService.GetPersona(personaID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch persona") + } + + return c.JSON(http.StatusOK, persona) +} + +func (p *PersonaController) GetPersonaTasks(c echo.Context) error { + personaID := c.Param("pid") + tasks, err := p.personaService.GetPersonaTasks(personaID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch persona tasks") + } + + return c.JSON(http.StatusOK, tasks) +} + +func (p *PersonaController) CreatePersona(c echo.Context) error { + var persona models.Persona + + if err := c.Bind(&persona); err != nil { + return err + } + + if err := services.ValidateData(c, persona); err != nil { + return c.JSON(http.StatusBadRequest, "Failed to validate the data") + } + + user, err := p.personaService.CreatePersona(persona) + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to create persona") + } + + return c.JSON(http.StatusOK, user) +} + +func (p *PersonaController) UpdatePersona(c echo.Context) error { + var persona models.Persona + + if err := c.Bind(&persona); err != nil { + return c.JSON(http.StatusNotFound, "Failed to bind persona") + } + + personaID := c.Param("pid") + persona, err := p.personaService.UpdatePersona(personaID, persona) + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to update persona") + } + + return c.JSON(http.StatusOK, persona) +} + +func (p *PersonaController) DeletePersona(c echo.Context) error { + personaID := c.Param("pid") + err := p.personaService.DeletePersona(personaID) + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to delete persona") + } + + return c.JSON(http.StatusOK, "Persona successfully deleted") +} diff --git a/server/src/controllers/profile.go b/server/src/controllers/profile.go new file mode 100644 index 0000000..de8963c --- /dev/null +++ b/server/src/controllers/profile.go @@ -0,0 +1,88 @@ +package controllers + +import ( + "net/http" + "server/src/models" + "server/src/services" + "server/src/types" + + "github.com/labstack/echo/v4" +) + +type ProfileController struct { + profileService services.ProfileServiceInterface +} + +func NewProfileController(profileService services.ProfileServiceInterface) *ProfileController { + return &ProfileController{profileService: profileService} +} + +func (p *ProfileController) GetProfile(c echo.Context) error { + profileID := c.Param("pid") + profile, err := p.profileService.GetProfile(profileID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch profile") + } + + return c.JSON(http.StatusOK, profile) +} + +func (p *ProfileController) CreateProfile(c echo.Context) error { + var profile models.Profile + + if err := services.ValidateData(c, profile); err != nil { + return c.JSON(http.StatusBadRequest, "Failed to validate the data"+err.Error()) + } + + createdUserProfile, err := p.profileService.CreateProfile(profile) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to create the profile") + } + + return c.JSON(http.StatusOK, createdUserProfile) +} + +func (p *ProfileController) UpdateProfile(c echo.Context) error { + var profile models.Profile + + if err := c.Bind(&profile); err != nil { + return c.JSON(http.StatusNotFound, "Failed to bind profile") + } + + profileID := c.Param("pid") + profile, err := p.profileService.UpdateProfile(profileID, profile) + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to update profile") + } + + return c.JSON(http.StatusOK, profile) +} + +func (p *ProfileController) InsertOnboardingResponse(c echo.Context) error { + var profile models.Profile + var onboardingResponse types.OnboardingResponse + profileID := c.Param("pid") + + if err := c.Bind(&onboardingResponse); err != nil { + return c.JSON(http.StatusBadRequest, "Failed to process the request") + } + + profile, err := p.profileService.InsertOnboardingResponse(profileID, onboardingResponse, profile) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to insert onboarding response") + } + + return c.JSON(http.StatusOK, profile) +} + +func (p *ProfileController) DeleteProfile(c echo.Context) error { + profileID := c.Param("pid") + err := p.profileService.DeleteProfile(profileID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to delete profile") + } + + return c.JSON(http.StatusOK, "Successfully deleted profile") +} diff --git a/server/src/controllers/subtask.go b/server/src/controllers/subtask.go new file mode 100644 index 0000000..1ce7f73 --- /dev/null +++ b/server/src/controllers/subtask.go @@ -0,0 +1,83 @@ +package controllers + +import ( + "net/http" + "server/src/models" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +type SubTaskController struct { + subTaskService services.SubTaskServiceInterface +} + +func NewSubTaskController(subTaskService services.SubTaskServiceInterface) *SubTaskController { + return &SubTaskController{subTaskService: subTaskService} +} + +func (t *SubTaskController) GetAllSubTasks(c echo.Context) error { + subtasks, err := t.subTaskService.GetAllSubTasks() + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch subtasks") + } + + return c.JSON(http.StatusOK, subtasks) +} + +func (t *SubTaskController) GetSubTasks(c echo.Context) error { + subTaskID := c.Param("sid") + subTask, err := t.subTaskService.GetSubTask(subTaskID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch subtask") + } + + return c.JSON(http.StatusOK, subTask) +} + +func (t *SubTaskController) CreateSubTask(c echo.Context) error { + var subTask models.SubTask + + if err := c.Bind(&subTask); err != nil { + return err + } + + if err := services.ValidateData(c, subTask); err != nil { + return c.JSON(http.StatusBadRequest, "Failed to validate the data"+err.Error()) + } + + createdTask, err := t.subTaskService.CreateSubTask(subTask) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to create the subtask") + } + + return c.JSON(http.StatusOK, createdTask) +} + +func (t *SubTaskController) UpdateSubTask(c echo.Context) error { + var subTask models.SubTask + + if err := c.Bind(&subTask); err != nil { + return c.JSON(http.StatusNotFound, "Failed to bind subtask") + } + + subTaskID := c.Param("sid") + subTask, err := t.subTaskService.UpdateSubTask(subTaskID, subTask) + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to update subtask") + } + + return c.JSON(http.StatusOK, subTask) +} + +func (t *SubTaskController) DeleteSubTask(c echo.Context) error { + subTaskID := c.Param("sid") + err := t.subTaskService.DeleteSubTask(subTaskID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to delete subtask") + } + + return c.JSON(http.StatusOK, "Subtask successfully deleted") +} diff --git a/server/src/controllers/task.go b/server/src/controllers/task.go new file mode 100644 index 0000000..9cd874a --- /dev/null +++ b/server/src/controllers/task.go @@ -0,0 +1,94 @@ +package controllers + +import ( + "net/http" + "server/src/models" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +type TaskController struct { + taskService services.TaskServiceInterface +} + +func NewTaskController(taskService services.TaskServiceInterface) *TaskController { + return &TaskController{taskService: taskService} +} + +func (t *TaskController) GetAllTasks(c echo.Context) error { + tasks, err := t.taskService.GetAllTasks() + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch tasks") + } + + return c.JSON(http.StatusOK, tasks) +} + +func (t *TaskController) GetTasks(c echo.Context) error { + taskID := c.Param("tid") + task, err := t.taskService.GetTask(taskID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch task") + } + + return c.JSON(http.StatusOK, task) +} + +func (t *TaskController) GetAllSubtasksOfTask(c echo.Context) error { + taskID := c.Param("tid") + subtasks, err := t.taskService.GetAllSubtasksOfTask(taskID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch subtasks") + } + + return c.JSON(http.StatusOK, subtasks) +} + +func (t *TaskController) CreateTask(c echo.Context) error { + var task models.Task + + if err := c.Bind(&task); err != nil { + return err + } + + if err := services.ValidateData(c, task); err != nil { + return c.JSON(http.StatusBadRequest, "Failed to validate the data"+err.Error()) + } + + createdTask, err := t.taskService.CreateTask(task) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to create the task") + } + + return c.JSON(http.StatusOK, createdTask) +} + +func (t *TaskController) UpdateTask(c echo.Context) error { + var task models.Task + + if err := c.Bind(&task); err != nil { + return c.JSON(http.StatusNotFound, "Failed to bind task") + } + + taskID := c.Param("tid") + task, err := t.taskService.UpdateTask(taskID, task) + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to update task") + } + + return c.JSON(http.StatusOK, task) +} + +func (t *TaskController) DeleteTask(c echo.Context) error { + taskID := c.Param("tid") + err := t.taskService.DeleteTask(taskID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to delete task") + } + + return c.JSON(http.StatusOK, "Task successfully deleted") +} diff --git a/server/src/controllers/user.go b/server/src/controllers/user.go new file mode 100644 index 0000000..263401d --- /dev/null +++ b/server/src/controllers/user.go @@ -0,0 +1,138 @@ +package controllers + +import ( + "net/http" + "server/src/models" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +type UserController struct { + userService services.UserServiceInterface +} + +func NewUserController(userService services.UserServiceInterface) *UserController { + return &UserController{userService: userService} +} + +func (u *UserController) GetAllUsers(c echo.Context) error { + users, err := u.userService.GetAllUsers() + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch users") + } + + return c.JSON(http.StatusOK, users) +} + +func (u *UserController) GetUser(c echo.Context) error { + userID := c.Param("uid") + user, err := u.userService.GetUser(userID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch user") + } + + return c.JSON(http.StatusOK, user) +} + +func (u *UserController) GetUserFromUsername(c echo.Context) error { + username := c.Param("username") + user, err := u.userService.GetUserFromUsername(username) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch user") + } + + return c.JSON(http.StatusOK, user) +} + +func (u *UserController) GetUserFromFirebaseID(c echo.Context) error { + firebaseID := c.Param("firebase_id") + user, err := u.userService.GetUserFromFirebaseID(firebaseID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch user") + } + + return c.JSON(http.StatusOK, user) +} + +func (u *UserController) GetUserPersona(c echo.Context) error { + userID := c.Param("uid") + persona, err := u.userService.GetUserPersona(userID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch user persona") + } + + return c.JSON(http.StatusOK, persona) +} + +func (u *UserController) GetUserTasks(c echo.Context) error { + userID := c.Param("uid") + tasks, err := u.userService.GetUserTasks(userID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch user tasks") + } + + return c.JSON(http.StatusOK, tasks) +} + +func (u *UserController) GetUserProfile(c echo.Context) error { + userID := c.Param("uid") + profile, err := u.userService.GetUserProfile(userID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to fetch user profile") + } + + return c.JSON(http.StatusOK, profile) +} + +func (u *UserController) CreateUser(c echo.Context) error { + var user models.User + + if err := c.Bind(&user); err != nil { + return c.JSON(http.StatusBadRequest, "Failed to process the request") + } + + if err := services.ValidateData(c, user); err != nil { + return c.JSON(http.StatusBadRequest, "Failed to validate the data"+err.Error()) + } + + createdUser, err := u.userService.CreateUser(user) + if err != nil { + return c.JSON(http.StatusInternalServerError, "Failed to create the user") + } + + return c.JSON(http.StatusOK, createdUser) +} + +func (u *UserController) UpdateUser(c echo.Context) error { + var user models.User + + if err := c.Bind(&user); err != nil { + return c.JSON(http.StatusNotFound, "Failed to bind user") + } + + userID := c.Param("uid") + user, err := u.userService.UpdateUser(userID, user) + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to update user") + } + + return c.JSON(http.StatusOK, user) +} + +func (u *UserController) DeleteUser(c echo.Context) error { + userID := c.Param("uid") + err := u.userService.DeleteUser(userID) + + if err != nil { + return c.JSON(http.StatusNotFound, "Failed to delete user") + } + + return c.JSON(http.StatusOK, "User successfully deleted") +} diff --git a/server/src/database/db.go b/server/src/database/db.go index d3ada3d..2fc495f 100644 --- a/server/src/database/db.go +++ b/server/src/database/db.go @@ -2,8 +2,11 @@ package database import ( "fmt" - "server/src/model" + "server/src/models" + "server/src/routes" + "server/src/services" + "github.com/labstack/echo/v4" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" @@ -28,6 +31,24 @@ func connectDatabase(host, user, password, dbname, port string) (*gorm.DB, error }) } +func AddRoutes(db *gorm.DB, e *echo.Echo) { + userService := services.UserService{DB: db} + profileService := services.ProfileService{DB: db} + personaService := services.PersonaService{DB: db} + taskService := services.TaskService{DB: db} + subTaskService := services.SubTaskService{DB: db} + fileService := services.FileService{DB: db} + // guideService := services.GuideService{DB: db} + + routes.UserRoutes(e.Group("/api/users"), &userService) + routes.ProfileRoutes(e.Group("/api/profile"), &profileService) + routes.PersonaRoutes(e.Group("/api/personas"), &personaService) + routes.TaskRoutes(e.Group("/api/tasks"), &taskService) + routes.SubTaskRoutes(e.Group("/api/subtasks"), &subTaskService) + routes.FileRoutes(e.Group("/api/files"), &fileService) + // routes.GuideRoutes(e.Group("/api/guides"), &guideService) +} + func InitDB() (*gorm.DB, error) { dbHost := "localhost" dbUser := "postgres" @@ -53,14 +74,14 @@ func InitDB() (*gorm.DB, error) { } if err := db.AutoMigrate( - &model.File{}, - &model.Persona{}, - &model.SubTaskProgress{}, - &model.SubTask{}, - &model.TaskProgress{}, - &model.Task{}, - &model.UserProfile{}, - &model.User{}, + &models.File{}, + &models.Persona{}, + &models.SubTaskProgress{}, + &models.SubTask{}, + &models.TaskProgress{}, + &models.Task{}, + &models.Profile{}, + &models.User{}, ); err != nil { return nil, fmt.Errorf("failed to perform database auto migration: %v", err) } diff --git a/server/src/main.go b/server/src/main.go index e1952cb..491c8d0 100644 --- a/server/src/main.go +++ b/server/src/main.go @@ -7,7 +7,6 @@ import ( "net/http" "os" "os/signal" - "server/src/controller" "server/src/database" "sync" "syscall" @@ -24,7 +23,8 @@ func main() { log.Fatal("Failed to initialize the database: ", err) } - controller.SetupControllers(e, db) + database.AddRoutes(db, e) + // godotenv.Load("../.env") TODO:, load env vars var wg sync.WaitGroup wg.Add(1) diff --git a/server/src/migrations/data.sql b/server/src/migrations/data.sql index a92b72c..16c4a29 100644 --- a/server/src/migrations/data.sql +++ b/server/src/migrations/data.sql @@ -5,12 +5,12 @@ INSERT INTO personas (persona_title, persona_description, created_at, updated_at ('Adventurous Optimist with Wealth', 'Expert driven and death positive', clock_timestamp(), clock_timestamp()); -- Creating test users -INSERT INTO users (username, password, email, persona_id, created_at, updated_at) VALUES -('testuser1', 'password', 'user1@example.com', 1, clock_timestamp(), clock_timestamp()), -('testuser2', 'password', 'user2@example.com', 2, clock_timestamp(), clock_timestamp()), -('testuser3', 'password', 'user3@example.com', 3, clock_timestamp(), clock_timestamp()), -('testuser4', 'password', 'user4@example.com', 1, clock_timestamp(), clock_timestamp()), -('testuser5', 'password', 'user5@example.com', 2, clock_timestamp(), clock_timestamp()); +INSERT INTO users (username, password, firebase_id, email, persona_id, created_at, updated_at) VALUES +('testuser1', 'password', 'abcdefgh', 'user1@example.com', 1, clock_timestamp(), clock_timestamp()), +('testuser2', 'password', 'ijklmn', 'user2@example.com', 2, clock_timestamp(), clock_timestamp()), +('testuser3', 'password', 'opqrst', 'user3@example.com', 3, clock_timestamp(), clock_timestamp()), +('testuser4', 'password', 'vwxyz', 'user4@example.com', 1, clock_timestamp(), clock_timestamp()), +('testuser5', 'password', '12345', 'user5@example.com', 2, clock_timestamp(), clock_timestamp()); -- Creating user profile INSERT INTO user_profiles (name, user_id, date_of_birth, phone_number, created_at, updated_at) VALUES diff --git a/server/src/model/file.go b/server/src/model/file.go deleted file mode 100644 index e419c3d..0000000 --- a/server/src/model/file.go +++ /dev/null @@ -1,12 +0,0 @@ -package model - -import "gorm.io/gorm" - -type File struct { - gorm.Model - FileName string `gorm:"type:varchar(255)" json:"file_name"` - FileDescription string `gorm:"type:text" json:"file_description"` - FilePath string `gorm:"type:varchar(255)" json:"file_path"` - UserID uint `json:"user_id"` - User User `gorm:"foreignkey:UserID" json:"-"` -} diff --git a/server/src/model/subtask_progress.go b/server/src/model/subtask_progress.go deleted file mode 100644 index 670eb26..0000000 --- a/server/src/model/subtask_progress.go +++ /dev/null @@ -1,12 +0,0 @@ -package model - -import "gorm.io/gorm" - -type SubTaskProgress struct { - gorm.Model - Completed bool `json:"completed"` - UserID int `json:"user_id"` - SubTaskID int `json:"subtask_id"` - User User `gorm:"foreignkey:UserID" json:"-"` - SubTask SubTask `gorm:"foreignkey:SubTaskID" json:"-"` -} diff --git a/server/src/model/task_progress.go b/server/src/model/task_progress.go deleted file mode 100644 index b57e6fd..0000000 --- a/server/src/model/task_progress.go +++ /dev/null @@ -1,12 +0,0 @@ -package model - -import "gorm.io/gorm" - -type TaskProgress struct { - gorm.Model - Completed bool `json:"completed"` - UserID uint `json:"user_id"` - TaskID uint `json:"task_id"` - User User `gorm:"foreignkey:UserID" json:"-"` - Task Task `gorm:"foreignkey:TaskID" json:"-"` -} diff --git a/server/src/model/user.go b/server/src/model/user.go deleted file mode 100644 index 2ef8c34..0000000 --- a/server/src/model/user.go +++ /dev/null @@ -1,15 +0,0 @@ -package model - -import ( - "gorm.io/gorm" -) - -type User struct { - gorm.Model - Username string `gorm:"type:varchar(255);unique" json:"username"` - FirebaseID string `gorm:"type:varchar(255);unique" json:"firebase_id"` - Password string `gorm:"type:text" json:"password"` - Email string `gorm:"type:varchar(255);unique" json:"email"` - PersonaID uint `json:"persona_id"` - Persona Persona `gorm:"foreignkey:PersonaID" json:"persona"` -} diff --git a/server/src/models/file.go b/server/src/models/file.go new file mode 100644 index 0000000..89d016f --- /dev/null +++ b/server/src/models/file.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm" + +type File struct { + gorm.Model + FileName string `gorm:"type:varchar(255);unique" json:"file_name"` + // FileDescription string `gorm:"type:text" json:"file_description" validate:"required"` + UserID uint `gorm:"foreignkey:User;unique" json:"user_id"` + User *User `gorm:"foreignkey:UserID" json:"-"` +} diff --git a/server/src/model/persona.go b/server/src/models/persona.go similarity index 58% rename from server/src/model/persona.go rename to server/src/models/persona.go index ba7d5ba..0a2182c 100644 --- a/server/src/model/persona.go +++ b/server/src/models/persona.go @@ -1,10 +1,10 @@ -package model +package models import "gorm.io/gorm" type Persona struct { gorm.Model - PersonaDescription string `gorm:"type:text" json:"persona_description"` - PersonaTitle string `gorm:"type:varchar(255)" json:"persona_title"` - Tasks []Task `gorm:"many2many:persona_tasks;" json:"-"` + PersonaDescription string `gorm:"type:text" json:"persona_description" validate:"required"` + PersonaTitle string `gorm:"type:varchar(255)" json:"persona_title" validate:"required"` + Tasks []Task `gorm:"many2many:persona_tasks;"` } diff --git a/server/src/model/user_profile.go b/server/src/models/profile.go similarity index 71% rename from server/src/model/user_profile.go rename to server/src/models/profile.go index f2b74e3..798ef9c 100644 --- a/server/src/model/user_profile.go +++ b/server/src/models/profile.go @@ -1,4 +1,4 @@ -package model +package models import ( "time" @@ -6,12 +6,12 @@ import ( "gorm.io/gorm" ) -type UserProfile struct { +type Profile struct { gorm.Model - Name string `gorm:"type:varchar(255)" json:"name"` - DateOfBirth time.Time `gorm:"type:date" json:"date_of_birth"` - PhoneNumber string `gorm:"type:varchar(20)" json:"phone_number"` + Name string `gorm:"type:varchar(255)" json:"name" validate:"required"` + DateOfBirth time.Time `gorm:"type:date" json:"date_of_birth" validate:"required"` + PhoneNumber string `gorm:"type:varchar(20)" json:"phone_number" validate:"required"` OnboardingResponse string `gorm:"type:jsonb;default:'{}'" json:"response"` UserID uint `gorm:"foreignkey:User;unique" json:"user_id"` - User User `json:"-"` + User *User `json:"-"` } diff --git a/server/src/model/subtask.go b/server/src/models/subtask.go similarity index 51% rename from server/src/model/subtask.go rename to server/src/models/subtask.go index 47d5ece..d8d8d39 100644 --- a/server/src/model/subtask.go +++ b/server/src/models/subtask.go @@ -1,4 +1,4 @@ -package model +package models import ( "gorm.io/gorm" @@ -6,8 +6,8 @@ import ( type SubTask struct { gorm.Model - TaskName string `gorm:"type:varchar(255)" json:"task_name"` - TaskDescription string `gorm:"type:text" json:"task_description"` - TaskID uint `json:"task_id"` - Task Task `gorm:"foreignkey:TaskID" json:"-"` + TaskName string `gorm:"type:varchar(255)" json:"task_name" validate:"required"` + TaskDescription string `gorm:"type:text" json:"task_description" validate:"required"` + TaskID uint `json:"task_id" validate:"required"` + Task *Task `gorm:"foreignkey:TaskID" json:"-"` } diff --git a/server/src/models/subtask_progress.go b/server/src/models/subtask_progress.go new file mode 100644 index 0000000..8bc22a0 --- /dev/null +++ b/server/src/models/subtask_progress.go @@ -0,0 +1,12 @@ +package models + +import "gorm.io/gorm" + +type SubTaskProgress struct { + gorm.Model + Completed bool `json:"completed" validate:"required"` + UserID int `json:"user_id" validate:"required"` + SubTaskID int `json:"subtask_id" validate:"required"` + User *User `gorm:"foreignkey:UserID" json:"-"` + SubTask *SubTask `gorm:"foreignkey:SubTaskID" json:"-"` +} diff --git a/server/src/model/task.go b/server/src/models/task.go similarity index 78% rename from server/src/model/task.go rename to server/src/models/task.go index e3b8668..a58e42d 100644 --- a/server/src/model/task.go +++ b/server/src/models/task.go @@ -1,4 +1,4 @@ -package model +package models import ( "gorm.io/gorm" @@ -6,7 +6,7 @@ import ( type Task struct { gorm.Model - TaskName string `gorm:"type:varchar(255)" json:"task_name"` - TaskDescription string `gorm:"type:text" json:"task_description"` + TaskName string `gorm:"type:varchar(255)" json:"task_name" validate:"required"` + TaskDescription string `gorm:"type:text" json:"task_description" validate:"required"` Personas []Persona `gorm:"many2many:persona_tasks;"` } diff --git a/server/src/models/task_progress.go b/server/src/models/task_progress.go new file mode 100644 index 0000000..f3d5df3 --- /dev/null +++ b/server/src/models/task_progress.go @@ -0,0 +1,12 @@ +package models + +import "gorm.io/gorm" + +type TaskProgress struct { + gorm.Model + Completed bool `json:"completed" validate:"required"` + UserID uint `json:"user_id" validate:"required"` + TaskID uint `json:"task_id" validate:"required"` + User *User `gorm:"foreignkey:UserID" json:"-"` + Task *Task `gorm:"foreignkey:TaskID" json:"-"` +} diff --git a/server/src/models/user.go b/server/src/models/user.go new file mode 100644 index 0000000..64a6955 --- /dev/null +++ b/server/src/models/user.go @@ -0,0 +1,15 @@ +package models + +import ( + "gorm.io/gorm" +) + +type User struct { + gorm.Model + Username string `gorm:"type:varchar(255);unique" json:"username" validate:"required"` + FirebaseID string `gorm:"type:varchar(255);unique" json:"firebase_id" validate:"required"` + Password string `gorm:"type:text" json:"password" validate:"required"` + Email string `gorm:"type:varchar(255);unique" json:"email" validate:"required,email"` + PersonaID *uint `json:"persona_id"` + Persona *Persona `gorm:"foreignkey:PersonaID" json:"-"` +} diff --git a/server/src/routes/file.go b/server/src/routes/file.go new file mode 100644 index 0000000..21d4008 --- /dev/null +++ b/server/src/routes/file.go @@ -0,0 +1,18 @@ +package routes + +import ( + "server/src/controllers" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +func FileRoutes(g *echo.Group, fileService services.FileServiceInterface) { + fileController := controllers.NewFileController(fileService) + + g.GET("/:uid/user", fileController.GetAllUserFiles) + g.GET("/:fid", fileController.GetFileObject) + g.GET("/:fid?days=:days", fileController.GetPresignedURL) + g.POST("/", fileController.CreateFile) + g.DELETE("/:fid", fileController.DeleteFile) +} diff --git a/server/src/routes/persona.go b/server/src/routes/persona.go new file mode 100644 index 0000000..faecc9d --- /dev/null +++ b/server/src/routes/persona.go @@ -0,0 +1,20 @@ +package routes + +import ( + "server/src/controllers" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +func PersonaRoutes(g *echo.Group, personaService services.PersonaServiceInterface) { + personaController := controllers.NewPersonaController(personaService) + + g.GET("/", personaController.GetAllPersonas) + g.GET("/:pid", personaController.GetPersona) + g.GET("/:pid/tasks", personaController.GetPersonaTasks) + + g.POST("/", personaController.CreatePersona) + g.PUT("/:pid", personaController.UpdatePersona) + g.DELETE("/:pid", personaController.DeletePersona) +} diff --git a/server/src/routes/profile.go b/server/src/routes/profile.go new file mode 100644 index 0000000..00ac160 --- /dev/null +++ b/server/src/routes/profile.go @@ -0,0 +1,18 @@ +package routes + +import ( + "server/src/controllers" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +func ProfileRoutes(g *echo.Group, profileService services.ProfileServiceInterface) { + profileController := controllers.NewProfileController(profileService) + + g.GET("/:pid", profileController.GetProfile) + g.POST("/", profileController.CreateProfile) + g.PUT("/:pid", profileController.UpdateProfile) + g.PUT("/response/:uid", profileController.InsertOnboardingResponse) + g.DELETE("/:pid", profileController.DeleteProfile) +} diff --git a/server/src/routes/subtask.go b/server/src/routes/subtask.go new file mode 100644 index 0000000..625cd52 --- /dev/null +++ b/server/src/routes/subtask.go @@ -0,0 +1,18 @@ +package routes + +import ( + "server/src/controllers" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +func SubTaskRoutes(g *echo.Group, subTaskService services.SubTaskServiceInterface) { + subtaskController := controllers.NewSubTaskController(subTaskService) + + g.GET("/", subtaskController.GetAllSubTasks) + g.GET("/:sid", subtaskController.GetSubTasks) + g.POST("/", subtaskController.CreateSubTask) + g.PUT("/:sid", subtaskController.UpdateSubTask) + g.DELETE("/:sid", subtaskController.DeleteSubTask) +} diff --git a/server/src/routes/task.go b/server/src/routes/task.go new file mode 100644 index 0000000..d59e0cb --- /dev/null +++ b/server/src/routes/task.go @@ -0,0 +1,19 @@ +package routes + +import ( + "server/src/controllers" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +func TaskRoutes(g *echo.Group, taskService services.TaskServiceInterface) { + taskController := controllers.NewTaskController(taskService) + + g.GET("/", taskController.GetAllTasks) + g.GET("/:tid", taskController.GetTasks) + g.GET("/:tid/subtasks", taskController.GetAllSubtasksOfTask) + g.POST("/", taskController.CreateTask) + g.PUT("/:tid", taskController.UpdateTask) + g.DELETE("/:tid", taskController.DeleteTask) +} diff --git a/server/src/routes/user.go b/server/src/routes/user.go new file mode 100644 index 0000000..f26e7a3 --- /dev/null +++ b/server/src/routes/user.go @@ -0,0 +1,25 @@ +package routes + +import ( + "server/src/controllers" + "server/src/services" + + "github.com/labstack/echo/v4" +) + +func UserRoutes(g *echo.Group, userService services.UserServiceInterface) { + userController := controllers.NewUserController(userService) + + g.GET("/", userController.GetAllUsers) + g.GET("/:uid", userController.GetUser) + g.GET("/username/:username", userController.GetUserFromUsername) + g.GET("/firebase/:firebaseid", userController.GetUserFromFirebaseID) + + g.GET("/:uid/persona", userController.GetUserPersona) + g.GET("/:uid/tasks", userController.GetUserTasks) + g.GET("/:uid/profile", userController.GetUserProfile) + + g.POST("/", userController.CreateUser) + g.PUT("/:uid", userController.UpdateUser) + g.DELETE("/:uid", userController.DeleteUser) +} diff --git a/server/src/services/file.go b/server/src/services/file.go new file mode 100644 index 0000000..87a3232 --- /dev/null +++ b/server/src/services/file.go @@ -0,0 +1,208 @@ +package services + +import ( + "errors" + "fmt" + "io" + "mime/multipart" + "server/src/models" + "strconv" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/s3" + "github.com/aws/aws-sdk-go/service/s3/s3manager" + "gorm.io/gorm" +) + +var BUCKET_NAME = "generate-legacy-storage" +var ID = "AKIA2WVH6R5ZEMKYG7VW" +var SECRET = "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" + +type FileServiceInterface interface { + GetAllUserFiles(id string) ([]models.File, error) + GetFile(id string) (models.File, error) + GetFileObject(id string) ([]byte, string, error) + GetPresignedURL(id string, days string) (string, error) + CreateFile(file models.File, data *multipart.FileHeader) (models.File, error) + DeleteFile(id string) error +} + +type FileService struct { + DB *gorm.DB +} + +func createAWSSession() (*session.Session, error) { + // TODO --> consider caching active session so we dont make f new one every time + sess, err := session.NewSession(&aws.Config{ + Region: aws.String("us-east-2"), + Credentials: credentials.NewStaticCredentials(ID, SECRET, ""), + }) + + if err != nil { + return nil, err + } + + return sess, nil +} + +func (f *FileService) GetAllUserFiles(id string) ([]models.File, error) { + var files []models.File + + if err := f.DB.Where("user_id = ?", id).Find(&files).Error; err != nil { + return nil, err + } + + return files, nil +} + +func (f *FileService) GetFile(id string) (models.File, error) { + var file models.File + + if err := f.DB.First(&file, id).Error; err != nil { + return models.File{}, err + } + + return file, nil +} + +func (f *FileService) GetFileObject(id string) ([]byte, string, error) { + file, err := f.GetFile(id) + if err != nil { + return nil, "", err + } + + sess, err := createAWSSession() + if err != nil { + return nil, "", err + } + + svc := s3.New(sess) + key := fmt.Sprintf("%v-%v", file.UserID, file.FileName) + + fileResponse, err := svc.GetObject(&s3.GetObjectInput{ + Bucket: aws.String(BUCKET_NAME), + Key: aws.String(key), + }) + + if err != nil { + return nil, "", err + } + + defer fileResponse.Body.Close() + + fileContent, err := io.ReadAll(fileResponse.Body) + if err != nil { + return nil, "", err + } + + return fileContent, file.FileName, nil +} + +func (f *FileService) GetPresignedURL(id string, days string) (string, error) { + file, err := f.GetFile(id) + if err != nil { + return "", err + } + + // create session and service client, then create presigned url + sess, err := createAWSSession() + if err != nil { + return "", err + } + + svc := s3.New(sess) + objectKey := fmt.Sprintf("%v-%v", file.UserID, file.FileName) + + req, _ := svc.GetObjectRequest(&s3.GetObjectInput{ + Bucket: aws.String(BUCKET_NAME), + Key: aws.String(objectKey), + }) + + daysInt, err := strconv.Atoi(days) + if err != nil { + return "", err + } + expiration := time.Duration(24*time.Hour) * time.Duration(daysInt) + + url, err := req.Presign(expiration) + if err != nil { + return "", err + } + + return url, nil +} + +func (f *FileService) CreateFile(file models.File, data *multipart.FileHeader) (models.File, error) { + file.FileName = data.Filename + file.UserID = 1 + + // Check if the file size is greater than 5 MB + if data.Size > 5000000 { + return models.File{}, errors.New("maximum file size 5 MB") + } + + src, err := data.Open() + if err != nil { + return models.File{}, errors.New("failed to open file") + } + defer src.Close() + + // Upload the file to the S3 bucket + sess, err := createAWSSession() + if err != nil { + return models.File{}, errors.New("failed to create AWS session") + } + + uploader := s3manager.NewUploader(sess) + filename := fmt.Sprintf("%v-%v", file.UserID, file.FileName) + + _, err = uploader.Upload(&s3manager.UploadInput{ + Bucket: aws.String(BUCKET_NAME), + Key: aws.String(filename), + Body: src, + }) + if err != nil { + return models.File{}, errors.New("failed to upload file to S3 bucket") + } + + // Create the file in the database + if err := f.DB.Create(&file).Error; err != nil { + return models.File{}, errors.New("failed to create file in database") + } + + return file, nil +} + +func (f *FileService) DeleteFile(id string) error { + var file models.File + + if err := f.DB.First(&file, id).Error; err != nil { + return err + } + + // create session and service client, then delete file + sess, err := createAWSSession() + if err != nil { + return err + } + + svc := s3.New(sess) + objectKey := fmt.Sprintf("%v-%v", file.UserID, file.FileName) + + _, err = svc.DeleteObject(&s3.DeleteObjectInput{ + Bucket: aws.String(BUCKET_NAME), + Key: aws.String(objectKey), + }) + if err != nil { + return err + } + + if err := f.DB.Delete(&file).Error; err != nil { + return err + } + + return nil +} diff --git a/server/src/services/persona.go b/server/src/services/persona.go index 0fa218d..0821025 100644 --- a/server/src/services/persona.go +++ b/server/src/services/persona.go @@ -1,46 +1,87 @@ package services import ( - "server/src/model" + "server/src/models" - "github.com/labstack/echo/v4" "gorm.io/gorm" ) -type PersonaServices struct { +type PersonaServiceInterface interface { + GetAllPersonas() ([]models.Persona, error) + GetPersona(id string) (models.Persona, error) + GetPersonaTasks(id string) ([]models.Task, error) + + CreatePersona(persona models.Persona) (models.Persona, error) + UpdatePersona(id string, persona models.Persona) (models.Persona, error) + DeletePersona(id string) error +} + +type PersonaService struct { DB *gorm.DB } -func (u *PersonaServices) GetPersonaAllTasks(c echo.Context) ([]map[string]interface{}, error) { - var persona model.Persona - personaID := c.Param("pid") +func (p *PersonaService) GetAllPersonas() ([]models.Persona, error) { + var persona []models.Persona + + if err := p.DB.Find(&persona).Error; err != nil { + return nil, err + } + + return persona, nil +} + +func (p *PersonaService) GetPersona(id string) (models.Persona, error) { + var persona models.Persona + + if err := p.DB.First(&persona, id).Error; err != nil { + return models.Persona{}, err + } + + return persona, nil +} + +func (p *PersonaService) GetPersonaTasks(id string) ([]models.Task, error) { + var tasks []models.Task - if err := u.DB.First(&persona, personaID).Error; err != nil { + if err := p.DB.Where("persona_id = ?", id).Find(&tasks).Error; err != nil { return nil, err } - // Retrieve tasks related to the persona - var tasks []model.Task - u.DB.Model(&persona).Association("Tasks").Find(&tasks) + return tasks, nil +} - // Create a slice to store the JSON response - var taskList []map[string]interface{} +func (p *PersonaService) CreatePersona(persona models.Persona) (models.Persona, error) { + if err := p.DB.Create(&persona).Error; err != nil { + return models.Persona{}, err + } - // Loop through the tasks and retrieve their related subtasks - for _, task := range tasks { - var subtasks []model.SubTask - if err := u.DB.Where("task_id = ?", task.ID).Find(&subtasks).Error; err != nil { - subtasks = []model.SubTask{} // No subtasks found - } + return persona, nil +} + +func (p *PersonaService) UpdatePersona(id string, persona models.Persona) (models.Persona, error) { + var oldPersona models.Persona + + if err := p.DB.First(&oldPersona, id).Error; err != nil { + return models.Persona{}, err + } - // Form the JSON response for each task with its related subtasks - taskInfo := map[string]interface{}{ - "task": task, - "subtasks": subtasks, - } + if err := p.DB.Model(&oldPersona).Updates(persona).Error; err != nil { + return models.Persona{}, err + } + + return oldPersona, nil +} + +func (p *PersonaService) DeletePersona(id string) error { + var persona models.Persona + + if err := p.DB.First(&persona, id).Error; err != nil { + return err + } - taskList = append(taskList, taskInfo) + if err := p.DB.Delete(&persona).Error; err != nil { + return err } - return taskList, nil + return nil } diff --git a/server/src/services/profile.go b/server/src/services/profile.go new file mode 100644 index 0000000..0399008 --- /dev/null +++ b/server/src/services/profile.go @@ -0,0 +1,97 @@ +package services + +import ( + "encoding/json" + "server/src/models" + "server/src/types" + + "gorm.io/gorm" +) + +type ProfileServiceInterface interface { + GetProfile(id string) (models.Profile, error) + CreateProfile(profile models.Profile) (models.Profile, error) + UpdateProfile(id string, profile models.Profile) (models.Profile, error) + InsertOnboardingResponse(id string, onboardingResponse types.OnboardingResponse, profile models.Profile) (models.Profile, error) + DeleteProfile(id string) error +} + +type ProfileService struct { + DB *gorm.DB +} + +func (p *ProfileService) GetProfile(id string) (models.Profile, error) { + var profile models.Profile + + if err := p.DB.First(&profile, id).Error; err != nil { + return models.Profile{}, err + } + + return profile, nil +} + +func (p *ProfileService) CreateProfile(profile models.Profile) (models.Profile, error) { + if err := p.DB.Create(&profile).Error; err != nil { + return models.Profile{}, err + } + + return profile, nil +} + +func (p *ProfileService) UpdateProfile(id string, profile models.Profile) (models.Profile, error) { + var oldProfile models.Profile + + if err := p.DB.First(&oldProfile, id).Error; err != nil { + return models.Profile{}, err + } + + if err := p.DB.Model(&oldProfile).Updates(&profile).Error; err != nil { + return models.Profile{}, err + } + + return oldProfile, nil +} + +func (p *ProfileService) InsertOnboardingResponse(id string, onboardingResponse types.OnboardingResponse, profile models.Profile) (models.Profile, error) { + // Check if the user profile exists + profile, err := p.GetProfile(id) + if err != nil { + return models.Profile{}, err + } + + // Check if the user profile already has an onboarding response + if profile.OnboardingResponse != "{}" { + return models.Profile{}, err + } + + // Marshal the onboarding response into JSON + response, err := json.Marshal(onboardingResponse) + if err != nil { + return models.Profile{}, err + } + + // Update the OnboardingResponse field of the user profile + profile.OnboardingResponse = string(response) + + // Update the user profile with the new onboarding response + profile, err = p.UpdateProfile(id, profile) + if err != nil { + return models.Profile{}, err + } + + return profile, nil +} + +func (p *ProfileService) DeleteProfile(id string) error { + var profile models.Profile + + if err := p.DB.First(&profile, id).Error; err != nil { + return err + } + + if err := p.DB.Delete(&profile).Error; err != nil { + return err + } + + return nil +} diff --git a/server/src/services/subtask.go b/server/src/services/subtask.go new file mode 100644 index 0000000..ec09e8f --- /dev/null +++ b/server/src/services/subtask.go @@ -0,0 +1,75 @@ +package services + +import ( + "server/src/models" + + "gorm.io/gorm" +) + +type SubTaskServiceInterface interface { + GetAllSubTasks() ([]models.SubTask, error) + GetSubTask(id string) (models.SubTask, error) + CreateSubTask(subTask models.SubTask) (models.SubTask, error) + UpdateSubTask(id string, subTask models.SubTask) (models.SubTask, error) + DeleteSubTask(id string) error +} + +type SubTaskService struct { + DB *gorm.DB +} + +func (s *SubTaskService) GetAllSubTasks() ([]models.SubTask, error) { + var subTask []models.SubTask + + if err := s.DB.Find(&subTask).Error; err != nil { + return []models.SubTask{}, err + } + + return subTask, nil +} + +func (s *SubTaskService) GetSubTask(id string) (models.SubTask, error) { + var task models.SubTask + + if err := s.DB.First(&task, id).Error; err != nil { + return models.SubTask{}, err + } + + return task, nil +} + +func (s *SubTaskService) CreateSubTask(subTask models.SubTask) (models.SubTask, error) { + if err := s.DB.Create(&subTask).Error; err != nil { + return models.SubTask{}, err + } + + return subTask, nil +} + +func (s *SubTaskService) UpdateSubTask(id string, subTask models.SubTask) (models.SubTask, error) { + var oldSubTask models.SubTask + + if err := s.DB.First(&oldSubTask, id).Error; err != nil { + return models.SubTask{}, err + } + + if err := s.DB.Model(&oldSubTask).Updates(&subTask).Error; err != nil { + return models.SubTask{}, err + } + + return oldSubTask, nil +} + +func (s *SubTaskService) DeleteSubTask(id string) error { + var subTask models.SubTask + + if err := s.DB.First(&subTask, id).Error; err != nil { + return err + } + + if err := s.DB.Delete(&subTask).Error; err != nil { + return err + } + + return nil +} diff --git a/server/src/services/task.go b/server/src/services/task.go new file mode 100644 index 0000000..5725894 --- /dev/null +++ b/server/src/services/task.go @@ -0,0 +1,86 @@ +package services + +import ( + "server/src/models" + + "gorm.io/gorm" +) + +type TaskServiceInterface interface { + GetAllTasks() ([]models.Task, error) + GetTask(id string) (models.Task, error) + GetAllSubtasksOfTask(id string) ([]models.SubTask, error) + CreateTask(task models.Task) (models.Task, error) + UpdateTask(id string, task models.Task) (models.Task, error) + DeleteTask(id string) error +} + +type TaskService struct { + DB *gorm.DB +} + +func (t *TaskService) GetAllTasks() ([]models.Task, error) { + var tasks []models.Task + + if err := t.DB.Find(&tasks).Error; err != nil { + return []models.Task{}, err + } + + return tasks, nil +} + +func (t *TaskService) GetTask(id string) (models.Task, error) { + var task models.Task + + if err := t.DB.First(&task, id).Error; err != nil { + return models.Task{}, err + } + + return task, nil +} + +func (t *TaskService) GetAllSubtasksOfTask(id string) ([]models.SubTask, error) { + var subtasks []models.SubTask + + if err := t.DB.Where("task_id = ?", id).Find(&subtasks).Error; err != nil { + return []models.SubTask{}, err + } + + return subtasks, nil +} + +func (t *TaskService) CreateTask(task models.Task) (models.Task, error) { + if err := t.DB.Create(&task).Error; err != nil { + return models.Task{}, err + } + + return task, nil +} + +func (t *TaskService) UpdateTask(id string, task models.Task) (models.Task, error) { + var oldTask models.Task + + if err := t.DB.First(&oldTask, id).Error; err != nil { + return models.Task{}, err + } + + if err := t.DB.Model(&oldTask).Updates(&task).Error; err != nil { + return models.Task{}, err + } + + return oldTask, nil +} + +func (t *TaskService) DeleteTask(id string) error { + var task models.Task + + if err := t.DB.First(&task, id).Error; err != nil { + return err + } + + if err := t.DB.Delete(&task).Error; err != nil { + return err + } + + return nil +} diff --git a/server/src/services/user.go b/server/src/services/user.go index ca3b4c8..c6749e7 100644 --- a/server/src/services/user.go +++ b/server/src/services/user.go @@ -1,93 +1,152 @@ package services import ( - "server/src/model" - "time" + "server/src/models" - "github.com/labstack/echo/v4" "gorm.io/gorm" ) +// TODO: Possible optimization is to pass the user object to the service as well + type UserServiceInterface interface { - GetAllUsers(c echo.Context) ([]model.User, error) - GetUser(c echo.Context) (*model.User, error) - CreateUser(c echo.Context) (*model.User, error) - UpdateUser(c echo.Context) (*model.User, error) - DeleteUser(c echo.Context) error + GetAllUsers() ([]models.User, error) + GetUser(id string) (models.User, error) + GetUserFromUsername(username string) (models.User, error) + GetUserFromFirebaseID(firebaseID string) (models.User, error) + GetUserPersona(id string) (models.Persona, error) + GetUserTasks(id string) ([]models.Task, error) + GetUserProfile(id string) (models.Profile, error) + + CreateUser(user models.User) (models.User, error) + UpdateUser(id string, user models.User) (models.User, error) + DeleteUser(id string) error } type UserService struct { DB *gorm.DB } -func (u *UserService) GetAllUsers(c echo.Context) ([]model.User, error) { - var users []model.User - - if err := u.DB.Omit("password").Find(&users).Error; err != nil { +// Gets all users (including soft deleted users) +func (u *UserService) GetAllUsers() ([]models.User, error) { + var users []models.User + if err := u.DB.Unscoped().Omit("password").Find(&users).Error; err != nil { return nil, err } return users, nil } -func (u *UserService) GetUser(c echo.Context) (*model.User, error) { - var user *model.User - - userID := c.Param("uid") - - if err := u.DB.Omit("password").First(&user, userID).Error; err != nil { - return nil, err +func (u *UserService) GetUser(id string) (models.User, error) { + var user models.User + if err := u.DB.Omit("password").First(&user, id).Error; err != nil { + return models.User{}, err } return user, nil } -func (u *UserService) CreateUser(c echo.Context) (*model.User, error) { - var user *model.User - - if err := validateData(c, &user); err != nil { - return nil, err +func (u *UserService) GetUserFromUsername(username string) (models.User, error) { + var user models.User + if err := u.DB.Where("username = ?", username).Omit("password").First(&user).Error; err != nil { + return models.User{}, err } - user.CreatedAt = time.Now() - user.UpdatedAt = time.Now() + return user, nil +} - if result := u.DB.Create(&user); result.Error != nil { - return nil, result.Error +func (u *UserService) GetUserFromFirebaseID(firebaseID string) (models.User, error) { + var user models.User + if err := u.DB.Where("firebase_id = ?", firebaseID).Omit("password").First(&user).Error; err != nil { + return models.User{}, err } return user, nil } -func (u *UserService) UpdateUser(c echo.Context) (*model.User, error) { - var user *model.User +func (u *UserService) GetUserPersona(id string) (models.Persona, error) { + var persona models.Persona + var user models.User - userID := c.Param("uid") + user, err := u.GetUser(id) + if err != nil { + return models.Persona{}, err + } + + if err := u.DB.Model(&user).Association("Persona").Find(&persona); err != nil { + return models.Persona{}, err + } + + return persona, nil +} - if err := u.DB.First(&user, userID).Error; err != nil { +func (u *UserService) GetUserTasks(id string) ([]models.Task, error) { + var tasks []models.Task + var persona models.Persona + + persona, err := u.GetUserPersona(id) + if err != nil { return nil, err } - if err := c.Bind(&user); err != nil { + if err := u.DB.Model(&persona).Association("Tasks").Find(&tasks); err != nil { return nil, err } - u.DB.Save(&user) + return tasks, nil +} + +func (u *UserService) GetUserProfile(id string) (models.Profile, error) { + var profile models.Profile + var user models.User + + user, err := u.GetUser(id) + if err != nil { + return models.Profile{}, err + } + + if err := u.DB.Where("user_id = ?", user.ID).First(&profile).Error; err != nil { + return models.Profile{}, err + } + + return profile, nil +} + +func (u *UserService) CreateUser(user models.User) (models.User, error) { + if err := u.DB.Create(&user).Error; err != nil { + return models.User{}, err + } user.Password = "" return user, nil } -func (u *UserService) DeleteUser(c echo.Context) error { - var user model.User - userID := c.Param("uid") +func (u *UserService) UpdateUser(id string, user models.User) (models.User, error) { + var oldUser models.User + + if err := u.DB.First(&oldUser, id).Error; err != nil { + return models.User{}, err + } + + if err := u.DB.Model(&oldUser).Updates(&user).Error; err != nil { + return models.User{}, err + } + + user.Password = "" + + return oldUser, nil +} + +func (u *UserService) DeleteUser(id string) error { + var user models.User - if err := u.DB.First(&user, userID).Error; err != nil { + if err := u.DB.First(&user, id).Error; err != nil { return err } - u.DB.Delete(&user) + if err := u.DB.Delete(&user).Error; err != nil { + return err + } return nil } diff --git a/server/src/services/validator.go b/server/src/services/validator.go index 26344e1..1676339 100644 --- a/server/src/services/validator.go +++ b/server/src/services/validator.go @@ -1,18 +1,14 @@ package services import ( - "github.com/go-playground/validator" + "github.com/go-playground/validator/v10" "github.com/labstack/echo/v4" ) // Validate the data sent to the server if the data is invalid, return an error otherwise, return nil -func validateData(c echo.Context, data interface{}) error { - if err := c.Bind(data); err != nil { - return err - } - - validator := validator.New() - if err := validator.Struct(data); err != nil { +func ValidateData(c echo.Context, model interface{}) error { + validate := validator.New(validator.WithRequiredStructEnabled()) + if err := validate.Struct(model); err != nil { return err } diff --git a/server/src/types/OnboardingResponse.go b/server/src/types/OnboardingResponse.go new file mode 100644 index 0000000..1f2276e --- /dev/null +++ b/server/src/types/OnboardingResponse.go @@ -0,0 +1,22 @@ +package types + +type OnboardingResponse struct { + WorldviewQ1 string `json:"worldviewQ1"` + WorldviewQ2 string `json:"worldviewQ2"` + WorldviewQ3 string `json:"worldviewQ3"` + WorldviewQ4 string `json:"worldviewQ4"` + WorldviewQ5 string `json:"worldviewQ5"` + WorldviewQ6 string `json:"worldviewQ6"` + EmotionalPatternQ1 string `json:"emotionalPatternQ1"` + EmotionalPatternQ2 string `json:"emotionalPatternQ2"` + EmotionalPatternQ3 string `json:"emotionalPatternQ3"` + WorkstyleQ1 string `json:"workstyleQ1"` + WorkstyleQ2 string `json:"workstyleQ2"` + WorkstyleQ3 string `json:"workstyleQ3"` + WorkstyleQ4 string `json:"workstyleQ4"` + SocialInclinationQ1 string `json:"socialInclinationQ1"` + SocialInclinationQ2 string `json:"socialInclinationQ2"` + SocialInclinationQ3 string `json:"socialInclinationQ3"` + FunnelActivitiesQ1 string `json:"funnelActivitiesQ1"` + FunnelActivitiesQ2 string `json:"funnelActivitiesQ2"` +} diff --git a/server/tests/user_test.go b/server/tests/user_test.go index d1d83e0..d28bc7a 100644 --- a/server/tests/user_test.go +++ b/server/tests/user_test.go @@ -1,42 +1,20 @@ package controller import ( - "net/http" - "net/http/httptest" - - "server/src/controller" - "server/src/database" - "testing" - - "github.com/labstack/echo/v4" - "gorm.io/gorm" ) -func initTestDB() (*echo.Echo, *gorm.DB) { - e := echo.New() - db, err := database.InitDB() - if err != nil { - panic("Failed to initialize the database: " + err.Error()) - } +// func initTestDB() (*echo.Echo, *gorm.DB) { +// e := echo.New() +// db, err := database.InitDB() +// if err != nil { +// panic("Failed to initialize the database: " + err.Error()) +// } - return e, db -} +// return e, db +// } func TestGetAllUsers(t *testing.T) { - e, db := initTestDB() - - req := httptest.NewRequest(http.MethodGet, "/api/users", nil) - rec := httptest.NewRecorder() - c := e.NewContext(req, rec) - - userController := controller.UserController{DB: db} - - if err := userController.GetAllUsers(c); err != nil { - t.Errorf("Error handling request: %v", err) - } - - if rec.Code != http.StatusOK { - t.Errorf("Expected status code %d, got %d", http.StatusOK, rec.Code) - } + // e, db := initTestDB() + // defer db.Close() } From f87d79c1ba834ce34bb39032505d02f9e9c8a300 Mon Sep 17 00:00:00 2001 From: David Oduneye <44040421+DOOduneye@users.noreply.github.com> Date: Wed, 1 Nov 2023 11:21:06 -0400 Subject: [PATCH 4/6] Update README.md --- server/README.md | 214 ----------------------------------------------- 1 file changed, 214 deletions(-) diff --git a/server/README.md b/server/README.md index a6bf586..43db518 100644 --- a/server/README.md +++ b/server/README.md @@ -39,217 +39,3 @@ - [REST API Tutorial](https://restfulapi.net/) - [REST API Best Practices](https://www.freecodecamp.org/news/rest-api-best-practices-rest-endpoint-design-examples/) - - - -Certainly! Below is how you can organize the code into a Controller, Service, and Route, following the example you provided: - -### 1. **File Model** -The file model remains unchanged. - -```go -type File struct { -    gorm.Model -    FileName        string `gorm:"type:varchar(255)" json:"file_name" validate:"required"` -    FileDescription string `gorm:"type:text" json:"file_description" validate:"required"` -    FilePath        string `gorm:"type:varchar(255)" json:"file_path" validate:"required"` -    UserID          uint   `json:"user_id" validate:"required"` -    User            *User  `gorm:"foreignkey:UserID" json:"-"` -} -``` - -### 2. **File Service** -The service will handle the business logic related to files. - -```go -package services - -import ( -    "server/src/models" -    "gorm.io/gorm" -) - -type FileServiceInterface interface { -    CreateFile(file models.File, userID uint) error -    GetFile(fileID uint) (models.File, error) -    DeleteFile(fileID uint) error -    GetAllFiles(userID uint) ([]models.File, error) -    // Add more methods as needed -} - -type FileService struct { -    DB *gorm.DB -} - -// Implement the methods from FileServiceInterface -``` - -### 3. **File Controller** -The controller will handle HTTP requests and responses. - -```go -package controllers - -import ( -    "net/http" -    "server/src/services" -    "github.com/labstack/echo/v4" -) - -type FileController struct { -    fileService services.FileServiceInterface -} - -func NewFileController(fileService services.FileServiceInterface) *FileController { -    return &FileController{fileService: fileService} -} - -// Implement handlers such as CreateFile, GetFile, DeleteFile, etc. -``` - -### 4. **File Routes** -Define the routes for handling file-related requests. - -```go -func FileRoutes(g *echo.Group, fileService services.FileServiceInterface) { -    fileController := controllers.NewFileController(fileService) - -    g.POST("/", fileController.CreateFile) -    g.GET("/:fid", fileController.GetFile) -    g.DELETE("/:fid", fileController.DeleteFile) -    g.GET("/user/:uid", fileController.GetAllFiles) -    // Add more routes as needed -} -``` - -### 5. **Remaining AWS-specific functions** -You can consider creating a utility or helper package where you keep AWS-specific functionalities like `createAwsSession()`, or you could incorporate them into the service layer as private methods. - -### Conclusion -- **Model**: Structure representing the data. -- **Service**: Contains the business logic and interactions with the database. -- **Controller**: Handles HTTP requests, calling the appropriate services. -- **Routes**: Defines the HTTP routes and endpoints. - -You might also want to create a separate utility or helper for AWS-specific operations. This organization follows a clean architecture, separating concerns and making the codebase easier to manage and extend. Note that the actual implementation inside the methods (e.g., interactions with the database and AWS services) should be written based on your application's specific needs and logic. - -Certainly! Below is the detailed implementation of the handlers, methods for services, controllers, and utilities/helpers. - -### **Utilities/Helpers (AWS Specific Operations)** - -```go -package utils - -import ( -    "github.com/aws/aws-sdk-go/aws" -    "github.com/aws/aws-sdk-go/aws/credentials" -    "github.com/aws/aws-sdk-go/aws/session" -) - -func CreateAWSSession() (*session.Session, error) { -    sess, err := session.NewSession(&aws.Config{ -        Region:      aws.String("us-east-2"), -        Credentials: credentials.NewStaticCredentials("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY", ""), -    }) - -    return sess, err -} -``` - -### **File Service** - -```go -package services - -import ( -    "errors" -    "server/src/models" -    "gorm.io/gorm" -    // Import other necessary packages like AWS SDK -) - -type FileService struct { -    DB *gorm.DB -    // You can also inject the AWS utility here if necessary -} - -func (fs *FileService) CreateFile(file models.File) error { -    // Your code for creating a file goes here. This could involve: -    // - Validating the file -    // - Saving it to AWS S3 -    // - Saving file metadata to your database - -    return nil // or return an error if something goes wrong -} - -func (fs *FileService) GetFile(fileID uint) (models.File, error) { -    var file models.File - -    result := fs.DB.First(&file, fileID) -    if result.Error != nil { -        return file, errors.New("file not found") -    } - -    return file, nil -} - -// Implement other methods like DeleteFile, GetAllFiles, etc. -``` - -### **File Controller** - -```go -package controllers - -import ( -    "net/http" -    "server/src/services" -    "github.com/labstack/echo/v4" -) - -type FileController struct { -    fileService services.FileService -} - -func (fc *FileController) CreateFile(c echo.Context) error { -    // Your code for handling the creation of a file goes here. -    // This could involve: -    // - Receiving file data from a client -    // - Calling the fileService.CreateFile method - -    return c.JSON(http.StatusCreated, "File successfully created") -} - -func (fc *FileController) GetFile(c echo.Context) error { -    fileID := c.Param("fid") // getting file ID from the route parameter - -    file, err := fc.fileService.GetFile(fileID) -    if err != nil { -        return c.JSON(http.StatusNotFound, err.Error()) -    } - -    return c.JSON(http.StatusOK, file) -} - -// Implement other handlers like DeleteFile, GetAllFiles, etc. -``` - -### **Routes** - -```go -func FileRoutes(g *echo.Group, fileService services.FileService) { -    fileController := controllers.NewFileController(fileService) - -    g.POST("/", fileController.CreateFile) -    g.GET("/:fid", fileController.GetFile) -    // Define other routes like DELETE, PUT, etc. -} -``` - -### **Explanation** -- **Utilities/Helpers**: A utility function to create an AWS session. -- **Service**: Handles the business logic, interacts with the database and AWS. -- **Controller**: Receives HTTP requests, communicates with services, and returns HTTP responses. -- **Routes**: Defines the HTTP endpoints and connects them to the controller functions. - -Make sure to replace `"YOUR_ACCESS_KEY"` and `"YOUR_SECRET_KEY"` in the utility function with your actual AWS credentials. Additionally, you might need to customize the error handling, validation, and other business logic according to your specific use case and error handling strategy. \ No newline at end of file From ed744eb026e57d85472a4201d384e70af0d690d4 Mon Sep 17 00:00:00 2001 From: David Oduneye Date: Wed, 1 Nov 2023 11:23:32 -0400 Subject: [PATCH 5/6] =?UTF-8?q?bump:=20version=200.2.0=20=E2=86=92=200.3.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cz.toml | 2 +- client-new/CHANGELOG.md | 81 ++++ client-new/yarn.lock | 806 +++++++++++++++++++++------------------- 3 files changed, 503 insertions(+), 386 deletions(-) create mode 100644 client-new/CHANGELOG.md diff --git a/.cz.toml b/.cz.toml index 973c69f..a73ff6e 100644 --- a/.cz.toml +++ b/.cz.toml @@ -2,6 +2,6 @@ name = "cz_conventional_commits" tag_format = "$version" version_scheme = "semver" -version = "0.2.0" +version = "0.3.0" update_changelog_on_bump = true major_version_zero = true diff --git a/client-new/CHANGELOG.md b/client-new/CHANGELOG.md new file mode 100644 index 0000000..c2871dc --- /dev/null +++ b/client-new/CHANGELOG.md @@ -0,0 +1,81 @@ +## 0.3.0 (2023-11-01) + +### Feat + +- **server**: implemented services, controller, route, etc. to improve code quality +- **HomeScreen**: added new HomeScreen component/screen +- **HomeScreen**: implemented a simple HomeScreen for allhands + +### Fix + +- **persona.go**: linting error +- **Router.tsx**: added route for GuidesPage + +## 0.2.0 (2023-10-19) + +### BREAKING CHANGE + +- Completely redos frontend + +### Feat + +- **Slider**: Make Slider update state +- **Onboarding-Flow**: Added boiler plate for Onboarding Context +- redo how the frontend is set up +- **migrations**: added insert, drop, and reset +- **db.go**: function to add data to the db + +### Fix + +- **Yarn-lock**: Fix node package issues that causes build to fail +- **taskfile.yaml**: added task kill function + +## 0.1.1 (2023-10-07) + +### Fix + +- **db.go**: added error checking for migration + +## 0.1.0 (2023-10-07) + +### Feat + +- **aws.go**: established s3 connectivity + +### Fix + +- added permissions +- **CI.yaml**: port change +- **CI.yaml**: remove alove instances of postgres +- **CI.yaml**: missing dependency +- **scripts/verify_os.sh**: added functionality to differ scripts per os +- **make-linter-happy**: made distinct err names +- **init.sql**: spelling + +## 0.0.4 (2023-09-28) + +### Fix + +- **init.sql**: foreign key constrains +- **init.sql**: bad sql statements, errors on migration + +### Refactor + +- **TestComponent.tsx**: updated the text +- **init.sql**: updated migrations file for creating the db +- installation process +- **main.go**: fucked it up again +- **testcomponent.tsx**: fucked it up a little bit +- installation process + +## 0.0.3 (2023-09-13) + +### Fix + +- **init_db.sh**: fixed path + +## 0.0.2 (2023-09-12) + +### Refactor + +- tidy diff --git a/client-new/yarn.lock b/client-new/yarn.lock index 49bc6c5..45a7907 100644 --- a/client-new/yarn.lock +++ b/client-new/yarn.lock @@ -1173,10 +1173,10 @@ mv "~2" safe-json-stringify "~1" -"@expo/cli@0.10.13": - version "0.10.13" - resolved "https://registry.yarnpkg.com/@expo/cli/-/cli-0.10.13.tgz#6503e6c477a8407986cd645952b0ad6177e08fe7" - integrity sha512-8ciyz+yIDih6zCNMWK0IyEv411W7vej/TaWIFGarogPVbFokXrUKr0aKoQG1RU1SLlY4eUpHakbIzqog+rhJdQ== +"@expo/cli@0.10.14": + version "0.10.14" + resolved "https://registry.yarnpkg.com/@expo/cli/-/cli-0.10.14.tgz#c2e94cbc62f1d724828b848d2aaf5c4906db1028" + integrity sha512-IIZ9mYYHpNkK9XJAWLPtwTwZmasDq/NJsHLPjLtw5la4ANjWWwKYUcl3XKBECKovSDn9WHEQHGsBz6cyKS88Mg== dependencies: "@babel/runtime" "^7.20.0" "@expo/code-signing-certificates" "0.0.5" @@ -1543,12 +1543,12 @@ "@firebase/util" "1.9.3" tslib "^2.1.0" -"@firebase/app-compat@0.2.20": - version "0.2.20" - resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.2.20.tgz#df996427ce781d51e439e6fee42e5d954645f7bb" - integrity sha512-FXgdjgwUruLMZMh0HDwLmbcu2ImckT10HPdXZyzIJoaor9OenoTQO2RLk2xvvOL/JJnszN6kmv56c+8qA4KFXQ== +"@firebase/app-compat@0.2.22": + version "0.2.22" + resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.2.22.tgz#34316e56d43c76537de0f887ad8928a2a3a27803" + integrity sha512-kyksJFA19Oz5HZmR56s/ziOM6ivDBF9JYwC0ufacooYNd2sQ3pRsi5MZAYb1FR9hCE7MgoHuPmTtBHA7S/Cv8g== dependencies: - "@firebase/app" "0.9.20" + "@firebase/app" "0.9.22" "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" "@firebase/util" "1.9.3" @@ -1559,10 +1559,10 @@ resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.0.tgz#35b5c568341e9e263b29b3d2ba0e9cfc9ec7f01e" integrity sha512-AeweANOIo0Mb8GiYm3xhTEBVCmPwTYAu9Hcd2qSkLuga/6+j9b1Jskl5bpiSQWy9eJ/j5pavxj6eYogmnuzm+Q== -"@firebase/app@0.9.20": - version "0.9.20" - resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.9.20.tgz#d5a1d21d3661bf1465189d1b7bde30a3cff97f95" - integrity sha512-cMTDHr+1GfYyHBSLLvvTE8ywlDCKk/E8cUZmfv0ODmUBB1vXgrICShj7yH9UYf6m7l6pxad8T+qI/oAoAkCp2Q== +"@firebase/app@0.9.22": + version "0.9.22" + resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.9.22.tgz#a3232d5bffde8ad4b0c81e23f7fd5e5f7718702e" + integrity sha512-4hbUg9ojPbn4Gj21Z/GnJbiLQYOzkwBDFT5vBkQgUJJGS28qQLG6eZZ1DwLKh8lcrNJc4MR90OPaJWhSzJCR2w== dependencies: "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" @@ -1570,12 +1570,12 @@ idb "7.1.1" tslib "^2.1.0" -"@firebase/auth-compat@0.4.6": - version "0.4.6" - resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.4.6.tgz#413568be48d23a17aa14438b8aad86556bd1e132" - integrity sha512-pKp1d4fSf+yoy1EBjTx9ISxlunqhW0vTICk0ByZ3e+Lp6ZIXThfUy4F1hAJlEafD/arM0oepRiAh7LXS1xn/BA== +"@firebase/auth-compat@0.4.8": + version "0.4.8" + resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.4.8.tgz#f78207b49d9baa5e6a8a28eb5029ea6503371d1c" + integrity sha512-qKX8BOl1qewBzpfAXl6/lKPW7fjnY8/3umiSFIGO8SHwLQ3LsAdNFPdwafouwMiKLo5MXxW4XdxNSI4ilt0Z5w== dependencies: - "@firebase/auth" "1.3.0" + "@firebase/auth" "1.3.2" "@firebase/auth-types" "0.12.0" "@firebase/component" "0.6.4" "@firebase/util" "1.9.3" @@ -1592,10 +1592,10 @@ resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.12.0.tgz#f28e1b68ac3b208ad02a15854c585be6da3e8e79" integrity sha512-pPwaZt+SPOshK8xNoiQlK5XIrS97kFYc3Rc7xmy373QsOJ9MmqXxLaYssP5Kcds4wd2qK//amx/c+A8O2fVeZA== -"@firebase/auth@1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-1.3.0.tgz#514d77309fdef5cc0ae81d5f57cb07bdaf6822d7" - integrity sha512-vjK4CHbY9aWdiVOrKi6mpa8z6uxeaf7LB/MZTHuZOiGHMcUoTGB6TeMbRShyqk1uaMrxhhZ5Ar/dR0965E1qyA== +"@firebase/auth@1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-1.3.2.tgz#e39576e49c949b0339467b8a839809cec7208eaa" + integrity sha512-ksYpeRACL8INRpFZzbCLLnI9NP+L3UH/+ebKo4oBjhc/dSwPbpw6E1wjdm0odB1U5xHhXD/5lpyeFQZ+jXyBxA== dependencies: "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" @@ -1643,13 +1643,13 @@ faye-websocket "0.11.4" tslib "^2.1.0" -"@firebase/firestore-compat@0.3.19": - version "0.3.19" - resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.3.19.tgz#71e14de8866fa8f30a6d55b68cc572f258feb11a" - integrity sha512-hRcW9oTyluap8Qko/yqtgk4O/BJmR4FxkvF+P6LVvoqtspKLfQL70jJvzr1gYCCXn2OY8XUI7Q9BVdsTzEEONA== +"@firebase/firestore-compat@0.3.21": + version "0.3.21" + resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.3.21.tgz#6e516c6a76393b89352f9eca0f9f12884265acb1" + integrity sha512-u17so8cP4FQBEJyivAbZc0kW09YBXBvhSmUXiB7swkOLemfZUmmPZQGJxZGa9y/M02euU1y4EzvWN/h/bkx8pg== dependencies: "@firebase/component" "0.6.4" - "@firebase/firestore" "4.3.0" + "@firebase/firestore" "4.3.2" "@firebase/firestore-types" "3.0.0" "@firebase/util" "1.9.3" tslib "^2.1.0" @@ -1659,10 +1659,10 @@ resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-3.0.0.tgz#f3440d5a1cc2a722d361b24cefb62ca8b3577af3" integrity sha512-Meg4cIezHo9zLamw0ymFYBD4SMjLb+ZXIbuN7T7ddXN6MGoICmOTq3/ltdCGoDCS2u+H1XJs2u/cYp75jsX9Qw== -"@firebase/firestore@4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-4.3.0.tgz#229de93fa15ed4898b423ea97a693b30e23f1751" - integrity sha512-FwSMCxGdUuA9Su74I9himAKJogzjU41IBjjnNf0+5smORMKtWlNeeXqMpljrhZubj5V+GmWyExf5UD3y1in6FA== +"@firebase/firestore@4.3.2": + version "4.3.2" + resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-4.3.2.tgz#21607f866b8d68e879ef6b4408f7f66b1ac78aa0" + integrity sha512-K4TwMbgArWw+XAEUYX/vtk+TVy9n1uLeJKSrQeb89lwfkfyFINGLPME6YleaS0ovD1ziLM5/0WgL1CR4s53fDg== dependencies: "@firebase/component" "0.6.4" "@firebase/logger" "0.4.0" @@ -1871,10 +1871,10 @@ dependencies: tslib "^2.4.0" -"@formatjs/icu-messageformat-parser@2.6.2": - version "2.6.2" - resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.6.2.tgz#9bbb29099416e4ce2c7df50029c48985d4f901b3" - integrity sha512-nF/Iww7sc5h+1MBCDRm68qpHTCG4xvGzYs/x9HFcDETSGScaJ1Fcadk5U/NXjXeCtzD+DhN4BAwKFVclHfKMdA== +"@formatjs/icu-messageformat-parser@2.7.0": + version "2.7.0" + resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.7.0.tgz#9b13f2710a3b4efddfeb544480f684f27a53483b" + integrity sha512-7uqC4C2RqOaBQtcjqXsSpGRYVn+ckjhNga5T/otFh6MgxRrCJQqvjfbrGLpX1Lcbxdm5WH3Z2WZqt1+Tm/cn/Q== dependencies: "@formatjs/ecma402-abstract" "1.17.2" "@formatjs/icu-skeleton-parser" "1.6.2" @@ -1906,9 +1906,9 @@ integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ== "@grpc/grpc-js@~1.9.0": - version "1.9.5" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.5.tgz#22e283754b7b10d1ad26c3fb21849028dcaabc53" - integrity sha512-iouYNlPxRAwZ2XboDT+OfRKHuaKHiqjB5VFYZ0NFrHkbEF+AV3muIUY9olQsp8uxU4VvRCMiRk9ftzFDGb61aw== + version "1.9.9" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.9.tgz#ce3a05439b1c957ec64c2ecdc6f1e4f54e8af797" + integrity sha512-vQ1qwi/Kiyprt+uhb1+rHMpyk4CVRMTGNUGGPRGS7pLNfWkdCHrGEnT6T3/JyC2VZgoOX/X1KwdoU0WYQAeYcQ== dependencies: "@grpc/proto-loader" "^0.7.8" "@types/node" ">=12.12.47" @@ -2067,9 +2067,9 @@ integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.19" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz#f8a3249862f91be48d3127c3cfe992f79b4b8811" - integrity sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw== + version "0.3.20" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f" + integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -2165,13 +2165,13 @@ integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw== "@react-aria/checkbox@^3.2.1": - version "3.11.1" - resolved "https://registry.yarnpkg.com/@react-aria/checkbox/-/checkbox-3.11.1.tgz#80cf9548a8d8aee08cf91c0fb3bd21eeada5afa9" - integrity sha512-lg6vwUjxrBgh8ZOBfiI/BI4DQpH6nTzYEc7abjVIdp3Vgwvr6gnllxw58+JcsRVa/Iw2BRyWW0KZiKB1e/pb7Q== + version "3.11.2" + resolved "https://registry.yarnpkg.com/@react-aria/checkbox/-/checkbox-3.11.2.tgz#9e1045edf282298cb8337fd3fd1d953c6cf5f667" + integrity sha512-8cgXxpc7IMJ9buw+Rbhr1xc66zNp2ePuFpjw3uWyH7S3IJEd2f5kXUDNWLXQRADJso95UlajRlJQiG4QIObEnA== dependencies: - "@react-aria/label" "^3.7.1" - "@react-aria/toggle" "^3.8.1" - "@react-aria/utils" "^3.21.0" + "@react-aria/label" "^3.7.2" + "@react-aria/toggle" "^3.8.2" + "@react-aria/utils" "^3.21.1" "@react-stately/checkbox" "^3.5.1" "@react-stately/toggle" "^3.6.3" "@react-types/checkbox" "^3.5.2" @@ -2179,82 +2179,82 @@ "@swc/helpers" "^0.5.0" "@react-aria/combobox@^3.0.0-alpha.1": - version "3.7.0" - resolved "https://registry.yarnpkg.com/@react-aria/combobox/-/combobox-3.7.0.tgz#3352bcd8e7e95218c32b4d771207fb6927b7ee63" - integrity sha512-rrTptAsugPzcO7MqWMIuSpoNYpLBUOaGeRD6pOiNNPm/lAooZSYQg1AxM2m7pdE2gQQsiLInRbq/KvcfYMnDfQ== + version "3.7.1" + resolved "https://registry.yarnpkg.com/@react-aria/combobox/-/combobox-3.7.1.tgz#8fc26008b54bd2d2c6eac6c126c1b2bba5a5e774" + integrity sha512-37no1b3sRI9mDh3MpMPWNt0Q8QdoRipnx12Vx5Uvtb0PA23hwOWDquICzs157SoJpXP49/+eH6LiA0uTsqwVuQ== dependencies: - "@react-aria/i18n" "^3.8.3" - "@react-aria/interactions" "^3.19.0" - "@react-aria/listbox" "^3.11.0" + "@react-aria/i18n" "^3.8.4" + "@react-aria/interactions" "^3.19.1" + "@react-aria/listbox" "^3.11.1" "@react-aria/live-announcer" "^3.3.1" - "@react-aria/menu" "^3.11.0" - "@react-aria/overlays" "^3.18.0" - "@react-aria/selection" "^3.17.0" - "@react-aria/textfield" "^3.12.1" - "@react-aria/utils" "^3.21.0" + "@react-aria/menu" "^3.11.1" + "@react-aria/overlays" "^3.18.1" + "@react-aria/selection" "^3.17.1" + "@react-aria/textfield" "^3.12.2" + "@react-aria/utils" "^3.21.1" "@react-stately/collections" "^3.10.2" "@react-stately/combobox" "^3.7.1" - "@react-stately/layout" "^3.13.2" + "@react-stately/layout" "^3.13.3" "@react-types/button" "^3.9.0" "@react-types/combobox" "^3.8.1" "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" -"@react-aria/focus@^3.14.2", "@react-aria/focus@^3.2.3": - version "3.14.2" - resolved "https://registry.yarnpkg.com/@react-aria/focus/-/focus-3.14.2.tgz#aba74e40a985ba03c44a04aee0dc48e2a563b830" - integrity sha512-ozP3g+C/fp3BAgI7dhFgBSzJCOwlW+pKaUlv7ay+btzXX0nc3jgt26uPSDr+Yv2tQcHcQnxfP0kHlXLS7to+lA== +"@react-aria/focus@^3.14.3", "@react-aria/focus@^3.2.3": + version "3.14.3" + resolved "https://registry.yarnpkg.com/@react-aria/focus/-/focus-3.14.3.tgz#5e66dbf47e1d92aebf67d52b3b08d1631591f5b6" + integrity sha512-gvO/frZ7SxyfyHJYC+kRsUXnXct8hGHKlG1TwbkzCCXim9XIPKDgRzfNGuFfj0i8ZpR9xmsjOBUkHZny0uekFA== dependencies: - "@react-aria/interactions" "^3.19.0" - "@react-aria/utils" "^3.21.0" + "@react-aria/interactions" "^3.19.1" + "@react-aria/utils" "^3.21.1" "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" clsx "^1.1.1" -"@react-aria/i18n@^3.2.0", "@react-aria/i18n@^3.3.0", "@react-aria/i18n@^3.8.3": - version "3.8.3" - resolved "https://registry.yarnpkg.com/@react-aria/i18n/-/i18n-3.8.3.tgz#dd61061d5306edcb8761b9cebfc40fd1bb396e09" - integrity sha512-Q3jF+cwXfFIJFeCMX5M+JX8qcNm3TEoWFrcFGfYoKnq740zaWosuuAaGh2iSfUUooDtwGG6X6uUJbZfBIK4j4w== +"@react-aria/i18n@^3.2.0", "@react-aria/i18n@^3.3.0", "@react-aria/i18n@^3.8.4": + version "3.8.4" + resolved "https://registry.yarnpkg.com/@react-aria/i18n/-/i18n-3.8.4.tgz#e7ecd3edcaa66ceaf9ebb1034395e021685163af" + integrity sha512-YlTJn7YJlUxds/T5dNtme551qc118NoDQhK+IgGpzcmPQ3xSnwBAQP4Zwc7wCpAU+xEwnNcsGw+L1wJd49He/A== dependencies: "@internationalized/date" "^3.5.0" "@internationalized/message" "^3.1.1" "@internationalized/number" "^3.3.0" "@internationalized/string" "^3.1.1" "@react-aria/ssr" "^3.8.0" - "@react-aria/utils" "^3.21.0" + "@react-aria/utils" "^3.21.1" "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" -"@react-aria/interactions@^3.19.0", "@react-aria/interactions@^3.3.2": - version "3.19.0" - resolved "https://registry.yarnpkg.com/@react-aria/interactions/-/interactions-3.19.0.tgz#37c14668e43f5c1fc737ddfa3cdf77311ce9c858" - integrity sha512-nJ8VTmEOYJAAvV7wzeQVnamxWd3j16hGAzG++onjhluSWWKO1jMRN6WG9LDwvT5mBI0VYwf7JdVB3QBaCa9fsQ== +"@react-aria/interactions@^3.19.1", "@react-aria/interactions@^3.3.2": + version "3.19.1" + resolved "https://registry.yarnpkg.com/@react-aria/interactions/-/interactions-3.19.1.tgz#b17b1f9dc84624d4222c7fa0a4fa6b4c14fe125a" + integrity sha512-2QFOvq/rJfMGEezmtYcGcJmfaD16kHKcSTLFrZ8aeBK6hYFddGVZJZk+dXf+G7iNaffa8rMt6uwzVe/malJPBA== dependencies: "@react-aria/ssr" "^3.8.0" - "@react-aria/utils" "^3.21.0" + "@react-aria/utils" "^3.21.1" "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" -"@react-aria/label@^3.1.1", "@react-aria/label@^3.7.1": - version "3.7.1" - resolved "https://registry.yarnpkg.com/@react-aria/label/-/label-3.7.1.tgz#87fe414506481dadbec684a8252b42ca7d090855" - integrity sha512-/MMHGXVlz6HvZyPDX9mu4an8rM8v5t68jGnyBoaAL8oultWHI1bVRJ/Ro8rT0zY/68m5EWtwNYNyvcZ2X3JZ/w== +"@react-aria/label@^3.1.1", "@react-aria/label@^3.7.2": + version "3.7.2" + resolved "https://registry.yarnpkg.com/@react-aria/label/-/label-3.7.2.tgz#6563495cad2af9262e722514e88406baede48852" + integrity sha512-rS0xQy+4RH1+JLESzLZd9H285McjNNf2kKwBhzU0CW3akjlu7gqaMKEJhX9MlpPDIVOUc2oEObGdU3UMmqa8ew== dependencies: - "@react-aria/utils" "^3.21.0" + "@react-aria/utils" "^3.21.1" "@react-types/label" "^3.8.1" "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" -"@react-aria/listbox@^3.11.0", "@react-aria/listbox@^3.2.4": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@react-aria/listbox/-/listbox-3.11.0.tgz#54b75e90736f89643d2123509840aacad8ab5242" - integrity sha512-N82ISTmnUWsp2Bmo/Kjy+3l/1/CSfRl/y6U3vUMZzEc+v4ptgWscUoWMpqzDrBpYhbVx1RdFuFJYOYOv4M5QYQ== - dependencies: - "@react-aria/focus" "^3.14.2" - "@react-aria/interactions" "^3.19.0" - "@react-aria/label" "^3.7.1" - "@react-aria/selection" "^3.17.0" - "@react-aria/utils" "^3.21.0" +"@react-aria/listbox@^3.11.1", "@react-aria/listbox@^3.2.4": + version "3.11.1" + resolved "https://registry.yarnpkg.com/@react-aria/listbox/-/listbox-3.11.1.tgz#2a2c88daf6a67e07ab17440f72a859913161e6e8" + integrity sha512-AkguQaIkqpP5oe++EZqYHowD7FfeQs+yY0QZVSsVPpNExcBug8/GcXvhSclcOxdh6ekZg4Wwcq7K0zhuTSOPzg== + dependencies: + "@react-aria/focus" "^3.14.3" + "@react-aria/interactions" "^3.19.1" + "@react-aria/label" "^3.7.2" + "@react-aria/selection" "^3.17.1" + "@react-aria/utils" "^3.21.1" "@react-stately/collections" "^3.10.2" "@react-stately/list" "^3.10.0" "@react-types/listbox" "^3.4.5" @@ -2268,17 +2268,17 @@ dependencies: "@swc/helpers" "^0.5.0" -"@react-aria/menu@^3.11.0": - version "3.11.0" - resolved "https://registry.yarnpkg.com/@react-aria/menu/-/menu-3.11.0.tgz#7810d34f9b5f8a887c0498780f94468d8e2d47d7" - integrity sha512-rPHMHPkmdJdatxlvV4lYFA4z5d9HSlBS9b0LUsL5iheoyXIgdiD/WF4y6W5ye+j4ZnZTO1lA6hIopIcSE/G/vg== - dependencies: - "@react-aria/focus" "^3.14.2" - "@react-aria/i18n" "^3.8.3" - "@react-aria/interactions" "^3.19.0" - "@react-aria/overlays" "^3.18.0" - "@react-aria/selection" "^3.17.0" - "@react-aria/utils" "^3.21.0" +"@react-aria/menu@^3.11.1": + version "3.11.1" + resolved "https://registry.yarnpkg.com/@react-aria/menu/-/menu-3.11.1.tgz#fb31c5533d5106c41ed73c14516ecbf74742976a" + integrity sha512-1eVVDrGnSExaL7e8IiaM9ndWTjT23rsnQGUK3p66R1Ojs8Q5rPBuJpP74rsmIpYiKOCr8WyZunjm5Fjv5KfA5Q== + dependencies: + "@react-aria/focus" "^3.14.3" + "@react-aria/i18n" "^3.8.4" + "@react-aria/interactions" "^3.19.1" + "@react-aria/overlays" "^3.18.1" + "@react-aria/selection" "^3.17.1" + "@react-aria/utils" "^3.21.1" "@react-stately/collections" "^3.10.2" "@react-stately/menu" "^3.5.6" "@react-stately/tree" "^3.7.3" @@ -2287,17 +2287,17 @@ "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" -"@react-aria/overlays@^3.18.0", "@react-aria/overlays@^3.6.1", "@react-aria/overlays@^3.7.0": - version "3.18.0" - resolved "https://registry.yarnpkg.com/@react-aria/overlays/-/overlays-3.18.0.tgz#cba26f3cee1301999949d248979162c2456122c8" - integrity sha512-2y1QlDgR3CNN0koFFreSFlWgMuzhdZQ9CAVw6vUJaL5qZcIcS8H/1AzjNj81/sGrY2+iSauPpLNOh37lqDkKqQ== +"@react-aria/overlays@^3.18.1", "@react-aria/overlays@^3.7.0": + version "3.18.1" + resolved "https://registry.yarnpkg.com/@react-aria/overlays/-/overlays-3.18.1.tgz#b53093b2e1004feff155c81730e0101179cd6c47" + integrity sha512-C74eZbTp3OA/gXy9/+4iPrZiz7g27Zy6Q1+plbg5QTLpsFLBt2Ypy9jTTANNRZfW7a5NW/Bnw9WIRjCdtTBRXw== dependencies: - "@react-aria/focus" "^3.14.2" - "@react-aria/i18n" "^3.8.3" - "@react-aria/interactions" "^3.19.0" + "@react-aria/focus" "^3.14.3" + "@react-aria/i18n" "^3.8.4" + "@react-aria/interactions" "^3.19.1" "@react-aria/ssr" "^3.8.0" - "@react-aria/utils" "^3.21.0" - "@react-aria/visually-hidden" "^3.8.5" + "@react-aria/utils" "^3.21.1" + "@react-aria/visually-hidden" "^3.8.6" "@react-stately/overlays" "^3.6.3" "@react-types/button" "^3.9.0" "@react-types/overlays" "^3.8.3" @@ -2305,46 +2305,46 @@ "@swc/helpers" "^0.5.0" "@react-aria/radio@^3.1.2": - version "3.8.1" - resolved "https://registry.yarnpkg.com/@react-aria/radio/-/radio-3.8.1.tgz#ae27cfccdcbd3fe5e655d7eb26244e31dc9c5b60" - integrity sha512-RliB3qQ4/WhcZIN2XpQzDIO/Yhzei0OYYFYZKHLGLaFIiVI2phDZQLhQc35HEBBw3TvHnaO5NzGQmZ9zt5p5Jg== - dependencies: - "@react-aria/focus" "^3.14.2" - "@react-aria/i18n" "^3.8.3" - "@react-aria/interactions" "^3.19.0" - "@react-aria/label" "^3.7.1" - "@react-aria/utils" "^3.21.0" + version "3.8.2" + resolved "https://registry.yarnpkg.com/@react-aria/radio/-/radio-3.8.2.tgz#318fb1bbdc67131181c03002a5d8458405239b85" + integrity sha512-j8yyGjboTgoBEQWlnJbQVvegKiUeQEUvU/kZ7ZAdj+eAL3BqfO6FO7yt6WzK7ZIBzjGS9YbesaUa3hwIjDi3LA== + dependencies: + "@react-aria/focus" "^3.14.3" + "@react-aria/i18n" "^3.8.4" + "@react-aria/interactions" "^3.19.1" + "@react-aria/label" "^3.7.2" + "@react-aria/utils" "^3.21.1" "@react-stately/radio" "^3.9.1" "@react-types/radio" "^3.5.2" "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" -"@react-aria/selection@^3.17.0", "@react-aria/selection@^3.3.1", "@react-aria/selection@^3.3.2": - version "3.17.0" - resolved "https://registry.yarnpkg.com/@react-aria/selection/-/selection-3.17.0.tgz#29437753f4b276c96a8821e7476e5edcc2403667" - integrity sha512-Dmf2ri+czVDVIBdEq9KTbIqbohDaENnCUDCPqHmh87oJhrIZhgy29zsZIR5/j+zJzD59Ogy63weZ4yFnMzFtEw== +"@react-aria/selection@^3.17.1", "@react-aria/selection@^3.3.1", "@react-aria/selection@^3.3.2": + version "3.17.1" + resolved "https://registry.yarnpkg.com/@react-aria/selection/-/selection-3.17.1.tgz#12df277b8806fd26093e16f6a2734bd1e6fbb3e2" + integrity sha512-g5gkSc/M+zJiVgWbUpKN095ea0D4fxdluH9ZcXxN4AAvcrVfEJyAnMmWOIKRebN8xR0KPfNRnKB7E6jld2tbuQ== dependencies: - "@react-aria/focus" "^3.14.2" - "@react-aria/i18n" "^3.8.3" - "@react-aria/interactions" "^3.19.0" - "@react-aria/utils" "^3.21.0" + "@react-aria/focus" "^3.14.3" + "@react-aria/i18n" "^3.8.4" + "@react-aria/interactions" "^3.19.1" + "@react-aria/utils" "^3.21.1" "@react-stately/collections" "^3.10.2" "@react-stately/selection" "^3.14.0" "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" "@react-aria/slider@^3.0.1": - version "3.7.1" - resolved "https://registry.yarnpkg.com/@react-aria/slider/-/slider-3.7.1.tgz#00a992e9fb79d17543470afce81556e11f286c81" - integrity sha512-9fm2pszF+Ljf4fy9meJLh7zN+IwQkng+y2M5v1mg9BagOmupjoEYTPrZ5grrnJuD7FMgoXQ5sCr/kvHSZyfJnQ== - dependencies: - "@react-aria/focus" "^3.14.2" - "@react-aria/i18n" "^3.8.3" - "@react-aria/interactions" "^3.19.0" - "@react-aria/label" "^3.7.1" - "@react-aria/utils" "^3.21.0" + version "3.7.2" + resolved "https://registry.yarnpkg.com/@react-aria/slider/-/slider-3.7.2.tgz#e122bbf945c5ae0f72be1c8977ef9be957c4bdbf" + integrity sha512-io7yJm2jS0gK1ILE9kjClh9zylKsOLbRy748CyD66LDV0ZIjj2D/uZF6BtfKq7Zhc2OsMvDB9+e2IkrszKe8uw== + dependencies: + "@react-aria/focus" "^3.14.3" + "@react-aria/i18n" "^3.8.4" + "@react-aria/interactions" "^3.19.1" + "@react-aria/label" "^3.7.2" + "@react-aria/utils" "^3.21.1" "@react-stately/radio" "^3.9.1" - "@react-stately/slider" "^3.4.3" + "@react-stately/slider" "^3.4.4" "@react-types/radio" "^3.5.2" "@react-types/shared" "^3.21.0" "@react-types/slider" "^3.6.2" @@ -2372,36 +2372,36 @@ "@react-types/shared" "^3.2.1" "@react-types/tabs" "3.0.0-alpha.2" -"@react-aria/textfield@^3.12.1": - version "3.12.1" - resolved "https://registry.yarnpkg.com/@react-aria/textfield/-/textfield-3.12.1.tgz#f9994744c4906da6a42f075f7f37bcc6609d47cc" - integrity sha512-TOSpkspRvudUyYanvKjnZzj1q1MoyMUAtSDE+sn5IrB5R4XmwuIR9Wm3s8UxPJ/Wcnrb322s4k6J+7YpR5haWQ== +"@react-aria/textfield@^3.12.2": + version "3.12.2" + resolved "https://registry.yarnpkg.com/@react-aria/textfield/-/textfield-3.12.2.tgz#e1ae5abaf72ed9c800e6a8afface3b2fd58258ca" + integrity sha512-wRg8LJjZV6o4S/LRFqxs5waGDTiuIa/CRN+/X37Fu7GeZFeK0IBvWjKPlXLe7gMswaFqRmTKnQCU42mzUdDK1g== dependencies: - "@react-aria/focus" "^3.14.2" - "@react-aria/label" "^3.7.1" - "@react-aria/utils" "^3.21.0" + "@react-aria/focus" "^3.14.3" + "@react-aria/label" "^3.7.2" + "@react-aria/utils" "^3.21.1" "@react-types/shared" "^3.21.0" "@react-types/textfield" "^3.8.1" "@swc/helpers" "^0.5.0" -"@react-aria/toggle@^3.8.1": - version "3.8.1" - resolved "https://registry.yarnpkg.com/@react-aria/toggle/-/toggle-3.8.1.tgz#49a556987b31b3b7f2ba751a2e8c74ec9ac1d1a3" - integrity sha512-TGJdKIVcPHVH8zJ7RRTa5bGwO1+x6Sx3CM91V9O0Fhd5PlHxfob/eTrGMOCdmPeBUMd7rRBMfmGuQnp5e6iw9A== +"@react-aria/toggle@^3.8.2": + version "3.8.2" + resolved "https://registry.yarnpkg.com/@react-aria/toggle/-/toggle-3.8.2.tgz#4336f0d70e33347c7bcf43f3ec4e617ce449127b" + integrity sha512-0+RmlOQtyRmU+Dd9qM9od4DPpITC7jqA+n3aZn732XtCsosz5gPGbhFuLbSdWRZ42FQgqo7pZQWaDRZpJPkipA== dependencies: - "@react-aria/focus" "^3.14.2" - "@react-aria/interactions" "^3.19.0" - "@react-aria/utils" "^3.21.0" + "@react-aria/focus" "^3.14.3" + "@react-aria/interactions" "^3.19.1" + "@react-aria/utils" "^3.21.1" "@react-stately/toggle" "^3.6.3" "@react-types/checkbox" "^3.5.2" "@react-types/shared" "^3.21.0" "@react-types/switch" "^3.4.2" "@swc/helpers" "^0.5.0" -"@react-aria/utils@^3.21.0", "@react-aria/utils@^3.3.0", "@react-aria/utils@^3.4.1", "@react-aria/utils@^3.6.0": - version "3.21.0" - resolved "https://registry.yarnpkg.com/@react-aria/utils/-/utils-3.21.0.tgz#147a91188d74f1aa284ad6d3d7db24b0de069fca" - integrity sha512-0ZNaXgvbWnqqiG7FB0qhAIENN7CmBU30AnyTzz5ZZgvJexUJkhd2GMjvTqrBZ6zSjeMpUEIKg5PUA1eptGRPww== +"@react-aria/utils@^3.21.1", "@react-aria/utils@^3.3.0", "@react-aria/utils@^3.4.1", "@react-aria/utils@^3.6.0": + version "3.21.1" + resolved "https://registry.yarnpkg.com/@react-aria/utils/-/utils-3.21.1.tgz#35f5d545757ea38f05a0d2f5492f13217ebb03ce" + integrity sha512-tySfyWHXOhd/b6JSrSOl7krngEXN3N6pi1hCAXObRu3+MZlaZOMDf/j18aoteaIF2Jpv8HMWUJUJtQKGmBJGRA== dependencies: "@react-aria/ssr" "^3.8.0" "@react-stately/utils" "^3.8.0" @@ -2409,116 +2409,116 @@ "@swc/helpers" "^0.5.0" clsx "^1.1.1" -"@react-aria/visually-hidden@^3.2.1", "@react-aria/visually-hidden@^3.8.5": - version "3.8.5" - resolved "https://registry.yarnpkg.com/@react-aria/visually-hidden/-/visually-hidden-3.8.5.tgz#9c718f125fb6ab563e733bd1942eecffb5aa1d78" - integrity sha512-uJcYQ3FSuJIIvaRXrTdYl/EFMDML0WV5A8nl7IrO5AMTa2HG9CG04ufeFj2BH48gbbgzlRsiYM41SRSaKjYqBg== +"@react-aria/visually-hidden@^3.2.1", "@react-aria/visually-hidden@^3.8.6": + version "3.8.6" + resolved "https://registry.yarnpkg.com/@react-aria/visually-hidden/-/visually-hidden-3.8.6.tgz#9b149851ac41e9c72c7819f8d4ad47ddfb45b863" + integrity sha512-6DmS/JLbK9KgU/ClK1WjwOyvpn8HtwYn+uisMLdP7HlCm692peYOkXDR1jqYbHL4GlyLCD0JLI+/xGdVh5aR/w== dependencies: - "@react-aria/interactions" "^3.19.0" - "@react-aria/utils" "^3.21.0" + "@react-aria/interactions" "^3.19.1" + "@react-aria/utils" "^3.21.1" "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" clsx "^1.1.1" "@react-native-aria/button@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@react-native-aria/button/-/button-0.2.4.tgz#ce0c994449011f4b852a222afd90e027fb839de0" - integrity sha512-wlu6SXI20U+N4fbPX8oh9pkL9hx8W41+cra3fa3s2xfQ6czT4KAkyvSsr1ALUBH4dRkoxxSPOcGJMGnq2K3djw== + version "0.2.5" + resolved "https://registry.yarnpkg.com/@react-native-aria/button/-/button-0.2.5.tgz#e0221a963cb851259f4590c834f2382562cf4d0e" + integrity sha512-YQX1oW1gnlivB6lX6KD6dhKuS67rWM0HNsvmNHjvaPanqM9kvvJoV7rkoYXAIJA2vPmYHqHOvBoJj2R5lI9+9g== dependencies: "@react-aria/utils" "^3.6.0" - "@react-native-aria/interactions" "^0.2.3" + "@react-native-aria/interactions" "^0.2.11" "@react-stately/toggle" "^3.2.1" "@react-types/checkbox" "^3.2.1" "@react-native-aria/checkbox@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@react-native-aria/checkbox/-/checkbox-0.2.3.tgz#b6c99c215677df872f1bb4e596b54573f1c7a5f0" - integrity sha512-YtWtXGg5tvOaV6v1CmbusXoOZvGRAVYygms9qNeUF7/B8/iDNGSKjlxHE5LVOLRtJO/B9ndZnr6RkL326ceyng== + version "0.2.6" + resolved "https://registry.yarnpkg.com/@react-native-aria/checkbox/-/checkbox-0.2.6.tgz#80298eb1983e58d834fb9573e9082561368d60fa" + integrity sha512-is8riNMjLkdcpajcU928FwZMf6ZYmfT5+CEJH6NYmY/BoeYHri+w8UYqPIGi5+9//5nQAkpjopJx9Z7+jkEJlw== dependencies: "@react-aria/checkbox" "^3.2.1" "@react-aria/utils" "^3.6.0" - "@react-native-aria/toggle" "^0.2.3" - "@react-native-aria/utils" "^0.2.6" + "@react-native-aria/toggle" "^0.2.6" + "@react-native-aria/utils" "^0.2.10" "@react-stately/toggle" "^3.2.1" "@react-native-aria/combobox@^0.2.4-alpha.0": - version "0.2.4-alpha.1" - resolved "https://registry.yarnpkg.com/@react-native-aria/combobox/-/combobox-0.2.4-alpha.1.tgz#2ec7c5c2e87aba4dda62e494a4c3538066275e2b" - integrity sha512-MOxKMKVus9MsOL3l+mNRDYHeVr5kj5fYnretLofWh/dHBO2W5H7H70ZfOPDEr9s+vgaBBjHCtbbfOiimKRk6Kg== + version "0.2.5" + resolved "https://registry.yarnpkg.com/@react-native-aria/combobox/-/combobox-0.2.5.tgz#7a3553c0b9b287d673294f70137619b63d21f219" + integrity sha512-8rS2YKQ6Z7rrHg+oERgKydGzP0g2ER0mlBD1W75UlRWsGfL464tPVURK/mPoEj88irJMZO8B2qPVRMDlJk2gQQ== dependencies: "@react-aria/combobox" "^3.0.0-alpha.1" "@react-aria/live-announcer" "^3.0.0-alpha.0" - "@react-aria/overlays" "^3.6.1" + "@react-aria/overlays" "^3.7.0" "@react-aria/utils" "^3.6.0" - "@react-native-aria/utils" "^0.2.6" + "@react-native-aria/utils" "^0.2.10" "@react-types/button" "^3.3.1" "@react-native-aria/focus@^0.2.6": - version "0.2.8" - resolved "https://registry.yarnpkg.com/@react-native-aria/focus/-/focus-0.2.8.tgz#60192ae9b60e6833c964cd9dd296b557189ddf58" - integrity sha512-1dIby+o37J2m4oV59TkjlirOXvn5SWtr8Z2dYkHvPe8oip8pEzH/jIl8uXFyvQJmRYA9n7Ju5ucThJJ/4Py8hw== + version "0.2.9" + resolved "https://registry.yarnpkg.com/@react-native-aria/focus/-/focus-0.2.9.tgz#bdfa84f9711843df771877ac436ee3b4f8878b74" + integrity sha512-zVgOIzKwnsyyurUxlZnzUKB2ekK/cmK64sQJIKKUlkJKVxd2EAFf7Sjz/NVEoMhTODN3qGRASTv9bMk/pBzzVA== dependencies: "@react-aria/focus" "^3.2.3" -"@react-native-aria/interactions@^0.2.2", "@react-native-aria/interactions@^0.2.3", "@react-native-aria/interactions@^0.2.7": - version "0.2.10" - resolved "https://registry.yarnpkg.com/@react-native-aria/interactions/-/interactions-0.2.10.tgz#9e27191f589c8a04e627c3c7a3d465aaab5ee94d" - integrity sha512-J0Scz4ndwaqa13e7XwwKRx0jXhVCUAmT/i1udVYyXW/rANAXnnAxuWJDWuZOO/XiQ5eoN7OqIlYUkJG4NnDUOA== +"@react-native-aria/interactions@^0.2.11", "@react-native-aria/interactions@^0.2.2", "@react-native-aria/interactions@^0.2.7": + version "0.2.11" + resolved "https://registry.yarnpkg.com/@react-native-aria/interactions/-/interactions-0.2.11.tgz#033ed9675d67add72deaf6eeae02b005d0785276" + integrity sha512-qfdkD3DwYQm8UurvGLfdLFXPlU2QFdjYA0WWcDCKZD3R++rkpnFthExdws7kmsF1riKTaYcIN/R1MPTM4KZrsA== dependencies: "@react-aria/interactions" "^3.3.2" "@react-aria/utils" "^3.6.0" - "@react-native-aria/utils" "^0.2.6" + "@react-native-aria/utils" "^0.2.10" "@react-native-aria/listbox@^0.2.4-alpha.3": - version "0.2.4-alpha.3" - resolved "https://registry.yarnpkg.com/@react-native-aria/listbox/-/listbox-0.2.4-alpha.3.tgz#1a8df0de6c932c8143ea73e43713a5d37070203c" - integrity sha512-e/y+Wdoyy/PbpFj4DVYDYMsKI+uUqnZ/0yLByqHQvzs8Ys8o69CQkyEYzHhxvFT5lCLegkLbuQN2cJd8bYNQsA== + version "0.2.4" + resolved "https://registry.yarnpkg.com/@react-native-aria/listbox/-/listbox-0.2.4.tgz#ea2cd26de27ed54762add76d470ccb4a96eb684e" + integrity sha512-4Y4Jb/4iSc+MtjFKcT76XUOTgBbA5mUBBhnRQMCLLVE2i3ezBNC6lLNGFjXJNGfAKFqCJwz3YRXmlVu+BBtzqA== dependencies: "@react-aria/interactions" "^3.3.2" "@react-aria/label" "^3.1.1" "@react-aria/listbox" "^3.2.4" "@react-aria/selection" "^3.3.2" "@react-aria/utils" "^3.6.0" - "@react-native-aria/interactions" "^0.2.2" - "@react-native-aria/utils" "^0.2.6" + "@react-native-aria/interactions" "^0.2.11" + "@react-native-aria/utils" "^0.2.10" "@react-types/listbox" "^3.1.1" "@react-types/shared" "^3.4.0" "@react-native-aria/overlays@^0.3.3": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@react-native-aria/overlays/-/overlays-0.3.8.tgz#c38316c34435b0c1d15093147c1cf9e11d987306" - integrity sha512-nc0nN8HABFzWWim2qK8DT8/bST8OMyK1IFUm0M7T9lfpTsegLb3k+j8SqlVHBdHg1JaVXlXxNWQlHbszBQ+RJg== + version "0.3.10" + resolved "https://registry.yarnpkg.com/@react-native-aria/overlays/-/overlays-0.3.10.tgz#8123935f67acb3ab86b7cd3e947c0ba756f28dd3" + integrity sha512-x4+b+RblNe0hwlPFR6qzcmNixqB5/1b5xcN33IP6/BR6F04zHlsmWpHT5PT1qiYQPXLekqw6HGiWp3MC3ItsOw== dependencies: "@react-aria/interactions" "^3.3.2" "@react-aria/overlays" "^3.7.0" - "@react-native-aria/utils" "^0.2.8" + "@react-native-aria/utils" "^0.2.10" "@react-stately/overlays" "^3.1.1" "@react-types/overlays" "^3.4.0" dom-helpers "^5.0.0" "@react-native-aria/radio@^0.2.4": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@react-native-aria/radio/-/radio-0.2.5.tgz#436d3abdbb48bcaf6e9c5c045ff9c5bf87b71248" - integrity sha512-kTfCjRMZH+Z2C70VxjomPO8eXBcHPa5zcuOUotyhR10WsrKZJlwwnA75t2xDq8zsxKnABJRfThv7rSlAjkFSeg== + version "0.2.7" + resolved "https://registry.yarnpkg.com/@react-native-aria/radio/-/radio-0.2.7.tgz#162d59b75c18d01871973d5d8e28a965fd584346" + integrity sha512-wps3AtqPLL7UniS7ubkrP/qSZiaXC6elMVNA9Wr2ngyLjHJQb31an3MocDyD2tijLlH4zO+ExzOS7iz7wEYrJw== dependencies: "@react-aria/radio" "^3.1.2" "@react-aria/utils" "^3.6.0" - "@react-native-aria/interactions" "^0.2.3" - "@react-native-aria/utils" "^0.2.6" + "@react-native-aria/interactions" "^0.2.11" + "@react-native-aria/utils" "^0.2.10" "@react-stately/radio" "^3.2.1" "@react-types/radio" "^3.1.1" "@react-native-aria/slider@^0.2.5-alpha.1": - version "0.2.7" - resolved "https://registry.yarnpkg.com/@react-native-aria/slider/-/slider-0.2.7.tgz#ab79052388a64afe5818be05bd0b915214ff2007" - integrity sha512-9SacbsDHz8TlLJsC69dRpP15BhDv2sV1LtffVJvwufRoFCdKvEzYyWA6Mu7GxWQR7OoTzl4kYvP0IEArNAgczA== + version "0.2.9" + resolved "https://registry.yarnpkg.com/@react-native-aria/slider/-/slider-0.2.9.tgz#58c6aba74cbd03e4b3155bfee058552f6d4f7fc3" + integrity sha512-pyCiOy3L7SpzFHYsdGR054trfVMKizi/x10s5spzjXhMAEmYCuP5dEIo43DSz+ZieGGEk/cdvURxjVEwsgHznA== dependencies: "@react-aria/focus" "^3.2.3" "@react-aria/interactions" "^3.3.2" "@react-aria/label" "^3.1.1" "@react-aria/slider" "^3.0.1" "@react-aria/utils" "^3.6.0" - "@react-native-aria/utils" "^0.2.8" + "@react-native-aria/utils" "^0.2.10" "@react-stately/slider" "^3.0.1" "@react-native-aria/tabs@^0.2.7": @@ -2533,22 +2533,22 @@ "@react-stately/tabs" "3.0.0-alpha.1" "@react-types/tabs" "3.0.0-alpha.2" -"@react-native-aria/toggle@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@react-native-aria/toggle/-/toggle-0.2.3.tgz#a387f03480aa0d97dc0191acbcae66122f7bcf7f" - integrity sha512-3aOlchMxpR0b2h3Z7V0aYZaQMVJD6uKOWKWJm82VsLrni4iDnDX/mLv30ujuuK3+LclUhVlJd2kRuCl+xnf3XQ== +"@react-native-aria/toggle@^0.2.6": + version "0.2.6" + resolved "https://registry.yarnpkg.com/@react-native-aria/toggle/-/toggle-0.2.6.tgz#916832079a551d57bbc5842a09884700a2925579" + integrity sha512-uqsoh3ISY3yVh6HBH6jklrZ9eZgLqZ2A8s3XhxLGZIZV3SbhSP0LwwjTOqRIMXK12lvHixWneObD0GpR4i7v+g== dependencies: "@react-aria/focus" "^3.2.3" "@react-aria/utils" "^3.6.0" - "@react-native-aria/interactions" "^0.2.3" - "@react-native-aria/utils" "^0.2.6" + "@react-native-aria/interactions" "^0.2.11" + "@react-native-aria/utils" "^0.2.10" "@react-stately/toggle" "^3.2.1" "@react-types/checkbox" "^3.2.1" -"@react-native-aria/utils@^0.2.6", "@react-native-aria/utils@^0.2.7", "@react-native-aria/utils@^0.2.8": - version "0.2.8" - resolved "https://registry.yarnpkg.com/@react-native-aria/utils/-/utils-0.2.8.tgz#da433606506125483080f18dbcd97b526ca46fd5" - integrity sha512-x375tG1itv3irLFRnURLsdK2djuvhFJHizSDUtLCo8skQwfjslED5t4sUkQ49di4G850gaVJz0fCcCx/pHX7CA== +"@react-native-aria/utils@^0.2.10", "@react-native-aria/utils@^0.2.7", "@react-native-aria/utils@^0.2.8": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@react-native-aria/utils/-/utils-0.2.10.tgz#818c8940fb97850c0aff6ac4ae3004ccb1dff432" + integrity sha512-jaXMt9NEuLtOIWeHzOupVROVcNT9aZHhvHDMzoXzmWZ47/FUrAykXtilCpOiKTxYbcwuWKCvpDVjd/syoPyuYQ== dependencies: "@react-aria/ssr" "^3.0.1" "@react-aria/utils" "^3.3.0" @@ -2770,37 +2770,37 @@ invariant "^2.2.4" nullthrows "^1.1.1" -"@react-navigation/core@^6.4.9": - version "6.4.9" - resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.9.tgz#aa09ce534f5393427cb993cf242abdbd848fb2c7" - integrity sha512-G9GH7bP9x0qqupxZnkSftnkn4JoXancElTvFc8FVGfEvxnxP+gBo3wqcknyBi7M5Vad4qecsYjCOa9wqsftv9g== +"@react-navigation/core@^6.4.10": + version "6.4.10" + resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.10.tgz#0c52621968b35e3a75e189e823d3b9e3bad77aff" + integrity sha512-oYhqxETRHNHKsipm/BtGL0LI43Hs2VSFoWMbBdHK9OqgQPjTVUitslgLcPpo4zApCcmBWoOLX2qPxhsBda644A== dependencies: "@react-navigation/routers" "^6.1.9" escape-string-regexp "^4.0.0" nanoid "^3.1.23" query-string "^7.1.3" react-is "^16.13.0" - use-latest-callback "^0.1.5" + use-latest-callback "^0.1.7" -"@react-navigation/elements@^1.3.19": - version "1.3.19" - resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.19.tgz#18a4a754836af19c20d987e8ffc4f8b0ee2cbece" - integrity sha512-7hLvSYKPuDS070pza5gd43WDX7QgfuEmuTWNbCJhKdWlLudYmq3qzxGCBwCfO2dEI6+p8tla5wruaWiGKAbTYw== +"@react-navigation/elements@^1.3.21": + version "1.3.21" + resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.21.tgz#debac6becc6b6692da09ec30e705e476a780dfe1" + integrity sha512-eyS2C6McNR8ihUoYfc166O1D8VYVh9KIl0UQPI8/ZJVsStlfSTgeEEh+WXge6+7SFPnZ4ewzEJdSAHH+jzcEfg== "@react-navigation/native-stack@^6.9.14": - version "6.9.14" - resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.14.tgz#6c3baf9d308e9e07c4f2feafb722d57c5b156936" - integrity sha512-7RiZkvMFN6f0kmANc63B/0m9ttQ2JpDIPWQwPU93FP698s19KTOyu7uxgl7Oi3bvsqHFO5JfiR7B+4h8lh9dxw== + version "6.9.16" + resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.16.tgz#d3dfc1ebe51da34eff36d5475d7b33d982a59758" + integrity sha512-SrmBGr5YvRxDtdTacOkA/wvqwpt9kt+AsYpmt82hKMPKpu0v98WONedTXDzi6whhY3jeT2GZkwF8hyrJ+wDbTA== dependencies: - "@react-navigation/elements" "^1.3.19" + "@react-navigation/elements" "^1.3.21" warn-once "^0.1.0" "@react-navigation/native@^6.1.8": - version "6.1.8" - resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.8.tgz#2a451fc8e2eff667007feb25d75e1d2b87e5460d" - integrity sha512-0alti852nV+8oCVm9H80G6kZvrHoy51+rXBvVCRUs2rNDDozC/xPZs8tyeCJkqdw3cpxZDK8ndXF22uWq28+0Q== + version "6.1.9" + resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.9.tgz#8ef87095cd9c2ed094308c726157c7f6fc28796e" + integrity sha512-AMuJDpwXE7UlfyhIXaUCCynXmv69Kb8NzKgKJO7v0k0L+u6xUTbt6xvshmJ79vsvaFyaEH9Jg5FMzek5/S5qNw== dependencies: - "@react-navigation/core" "^6.4.9" + "@react-navigation/core" "^6.4.10" escape-string-regexp "^4.0.0" fast-deep-equal "^3.1.3" nanoid "^3.1.23" @@ -2894,14 +2894,14 @@ "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" -"@react-stately/layout@^3.13.2": - version "3.13.2" - resolved "https://registry.yarnpkg.com/@react-stately/layout/-/layout-3.13.2.tgz#24f5c93b1ddd345b7ace2bc72e9f88f73415da17" - integrity sha512-eucSC74XYhCJAUXLgj7FQgi85wXKkg3HFqanKh9qGOJGVH9vB/sbguV9syAOkeeWWfJFRMjAKSlRZOiPLG/x/A== +"@react-stately/layout@^3.13.3": + version "3.13.3" + resolved "https://registry.yarnpkg.com/@react-stately/layout/-/layout-3.13.3.tgz#65ca0ad8a4653122017c68ec2dc3a3d592296d02" + integrity sha512-AZ2Sm7iSRcRsNATXg7bjbPpZIjV3z7bHAJtICWA1wHieVVSV1FFoyDyiXdDTIOxyuGeytNPaxtGfPpFZia9Wsg== dependencies: "@react-stately/collections" "^3.10.2" "@react-stately/table" "^3.11.2" - "@react-stately/virtualizer" "^3.6.3" + "@react-stately/virtualizer" "^3.6.4" "@react-types/grid" "^3.2.2" "@react-types/shared" "^3.21.0" "@react-types/table" "^3.9.0" @@ -2992,13 +2992,13 @@ "@react-stately/utils" "^3.2.0" "@react-types/slider" "^3.0.1" -"@react-stately/slider@^3.0.1", "@react-stately/slider@^3.4.3": - version "3.4.3" - resolved "https://registry.yarnpkg.com/@react-stately/slider/-/slider-3.4.3.tgz#e138102d824e531c47a3c429de46a0e43d16596c" - integrity sha512-BWtDTnGRByAfk64t/xDMSaroYnwTVIguyzaHezy28wXGHxBl+l+qTSL2DCSokTSfqnfMs2FckXNh5LUVc8NjSg== +"@react-stately/slider@^3.0.1", "@react-stately/slider@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@react-stately/slider/-/slider-3.4.4.tgz#36a3f171077fb0e5bd7af7accdc228f5fd2fbe32" + integrity sha512-tFexbtN50zSo6e1Gi8K9MBfqgOo1eemF/VvFbde3PP9nG+ODcxEIajaYDPlMUuFw5cemJuoKo3+G5NBBn2/AjQ== dependencies: - "@react-aria/i18n" "^3.8.3" - "@react-aria/utils" "^3.21.0" + "@react-aria/i18n" "^3.8.4" + "@react-aria/utils" "^3.21.1" "@react-stately/utils" "^3.8.0" "@react-types/shared" "^3.21.0" "@react-types/slider" "^3.6.2" @@ -3077,12 +3077,12 @@ dependencies: "@swc/helpers" "^0.5.0" -"@react-stately/virtualizer@^3.6.3": - version "3.6.3" - resolved "https://registry.yarnpkg.com/@react-stately/virtualizer/-/virtualizer-3.6.3.tgz#c718df2dbffc26c85b6798ecfe6f1e1f296bf91f" - integrity sha512-vzasjzaKSz+ViqhApvSqRlX7+hhY2uMtjZ2kbCS0U/RtxXra4m5/dD6BfsZ4hGhjQ3PBebDfP9+JvrNQn5EjFQ== +"@react-stately/virtualizer@^3.6.4": + version "3.6.4" + resolved "https://registry.yarnpkg.com/@react-stately/virtualizer/-/virtualizer-3.6.4.tgz#fab655aa14d30a7241ff5751a0eb80552ac5d751" + integrity sha512-lf3+FDRnyLyY1IhLfwA6GuE/9F3nIEc5p245NkUSN1ngKlXI5PvLHNatiVbONC3wt90abkpMK+WMhu2S/B+4lA== dependencies: - "@react-aria/utils" "^3.21.0" + "@react-aria/utils" "^3.21.1" "@react-types/shared" "^3.21.0" "@swc/helpers" "^0.5.0" @@ -3266,93 +3266,93 @@ tslib "^2.4.0" "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" - integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#fdfdd69fa16d530047d9963635bd77c71a08c068" + integrity sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ== "@types/istanbul-lib-report@*": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#412e0725ef41cde73bfa03e0e833eaff41e0fd63" - integrity sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ== + version "3.0.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz#394798d5f727402eb5ec99eb9618ffcd2b7645a1" + integrity sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w== dependencies: "@types/istanbul-lib-coverage" "*" "@types/istanbul-reports@^3.0.0": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz#edc8e421991a3b4df875036d381fc0a5a982f549" - integrity sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A== + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz#0313e2608e6d6955d195f55361ddeebd4b74c6e7" + integrity sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg== dependencies: "@types/istanbul-lib-report" "*" "@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0": - version "20.8.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.6.tgz#0dbd4ebcc82ad0128df05d0e6f57e05359ee47fa" - integrity sha512-eWO4K2Ji70QzKUqRy6oyJWUeB7+g2cRagT3T/nxYibYcT4y2BDL8lqolRXjTHmkZCdJfIPaY73KbJAZmcryxTQ== + version "20.8.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.10.tgz#a5448b895c753ae929c26ce85cab557c6d4a365e" + integrity sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w== dependencies: - undici-types "~5.25.1" + undici-types "~5.26.4" "@types/prop-types@*": - version "15.7.8" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.8.tgz#805eae6e8f41bd19e88917d2ea200dc992f405d3" - integrity sha512-kMpQpfZKSCBqltAJwskgePRaYRFukDkm1oItcAbC3gNELR20XIBcN9VRgg4+m8DKsTfkWeA4m4Imp4DDuWy7FQ== + version "15.7.9" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.9.tgz#b6f785caa7ea1fe4414d9df42ee0ab67f23d8a6d" + integrity sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g== "@types/react-dom@^18.2.13": - version "18.2.13" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.13.tgz#89cd7f9ec8b28c8b6f0392b9591671fb4a9e96b7" - integrity sha512-eJIUv7rPP+EC45uNYp/ThhSpE16k22VJUknt5OLoH9tbXoi8bMhwLf5xRuWMywamNbWzhrSmU7IBJfPup1+3fw== + version "18.2.14" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.14.tgz#c01ba40e5bb57fc1dc41569bb3ccdb19eab1c539" + integrity sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ== dependencies: "@types/react" "*" "@types/react-native@^0.72.3": - version "0.72.3" - resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.72.3.tgz#eb5726eb3ec6b79a10db7a295cc0346eb5e9331a" - integrity sha512-9+g+DBJIY3bG7+ZlYzKPr9kxTQxUuZQgLWZhYK4RlIcrsm3qaJhL2PU2e/K4CjnzznWCo2Islgec94x2z1pG4Q== + version "0.72.5" + resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.72.5.tgz#33a0d0c3c724395ee05bb37255937dcb3fae6d5f" + integrity sha512-HAt+EC576kbyg3+qruzbOLgVhgDHTHJ3d3rTkWRJ0wukze+l3ldWUkh1IarERHqsUlWwmkuYu0+4TQE5y1EjwA== dependencies: "@react-native/virtualized-lists" "^0.72.4" "@types/react" "*" "@types/react@*", "@types/react@^18.2.28": - version "18.2.28" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.28.tgz#86877465c0fcf751659a36c769ecedfcfacee332" - integrity sha512-ad4aa/RaaJS3hyGz0BGegdnSRXQBkd1CCYDCdNjBPg90UUpLgo+WlJqb9fMYUxtehmzF3PJaTWqRZjko6BRzBg== + version "18.2.33" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.33.tgz#055356243dc4350a9ee6c6a2c07c5cae12e38877" + integrity sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" csstype "^3.0.2" "@types/scheduler@*": - version "0.16.4" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.4.tgz#fedc3e5b15c26dc18faae96bf1317487cb3658cf" - integrity sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ== + version "0.16.5" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.5.tgz#4751153abbf8d6199babb345a52e1eb4167d64af" + integrity sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw== "@types/stack-utils@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" - integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.2.tgz#01284dde9ef4e6d8cef6422798d9a3ad18a66f8b" + integrity sha512-g7CK9nHdwjK2n0ymT2CW698FuWJRIx+RP6embAzZ2Qi8/ilIrA1Imt2LVSeHUzKvpoi7BhmmQcXz95eS0f2JXw== "@types/yargs-parser@*": - version "21.0.1" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.1.tgz#07773d7160494d56aa882d7531aac7319ea67c3b" - integrity sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ== + version "21.0.2" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.2.tgz#7bd04c5da378496ef1695a1008bf8f71847a8b8b" + integrity sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw== "@types/yargs@^15.0.0": - version "15.0.16" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.16.tgz#258009dc52907e8f03041eb64ffdac297ba4b208" - integrity sha512-2FeD5qezW3FvLpZ0JpfuaEWepgNLl9b2gQYiz/ce0NhoB1W/D+VZu98phITXkADYerfr/jb7JcDcVhITsc9bwg== + version "15.0.17" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.17.tgz#bea870ba551b43831bfaa75de2e4a3849c39322b" + integrity sha512-cj53I8GUcWJIgWVTSVe2L7NJAB5XWGdsoMosVvUgv1jEnMbAcsbaCzt1coUcyi8Sda5PgTWAooG8jNyDTD+CWA== dependencies: "@types/yargs-parser" "*" "@types/yargs@^16.0.0": - version "16.0.6" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.6.tgz#cc0c63684d68d23498cf0b5f32aa4c3fb437c638" - integrity sha512-oTP7/Q13GSPrgcwEwdlnkoZSQ1Hg9THe644qq8PG6hhJzjZ3qj1JjEFPIwWV/IXVs5XGIVqtkNOS9kh63WIJ+A== + version "16.0.7" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.7.tgz#b0d0502cb5f6c17994df72a600049f10bbf17203" + integrity sha512-lQcYmxWuOfJq4IncK88/nwud9rwr1F04CFc5xzk0k4oKVyz/AI35TfsXmhjf6t8zp8mpCOi17BfvuNWx+zrYkg== dependencies: "@types/yargs-parser" "*" "@types/yargs@^17.0.8": - version "17.0.28" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.28.tgz#d106e4301fbacde3d1796ab27374dd16588ec851" - integrity sha512-N3e3fkS86hNhtk6BEnc0rj3zcehaxx8QWhCROJkqpl5Zaoi7nAic3jH8q94jVD3zu5LGk+PUB6KAiDmimYOEQw== + version "17.0.29" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.29.tgz#06aabc72497b798c643c812a8b561537fea760cf" + integrity sha512-nacjqA3ee9zRF/++a3FUY1suHTFKZeHba2n8WeDw9cCVdmzmHpIxyzOJBcpHvvEmS8E9KqWlSnWHUkOrkhWcvA== dependencies: "@types/yargs-parser" "*" @@ -3365,9 +3365,9 @@ wonka "^4.0.14" "@urql/core@>=2.3.1": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@urql/core/-/core-4.1.3.tgz#8b61f015425f9c96e8e9368d071d3f663a2bd926" - integrity sha512-Wapa58olpEJtZzSEuZNDxzBxmOmHuivG6Hb/QPc6HjHfCJ6f36gnlWc9a9TsC8Vddle+6PsS6+quMMTuj+bj7A== + version "4.1.4" + resolved "https://registry.yarnpkg.com/@urql/core/-/core-4.1.4.tgz#d1fe9f278b2d1ff32df2314b00d2d94009271665" + integrity sha512-wFm67yljv4uFAWNtPwcS1NMhF/n+p/68i+kZU6R1dPxhfq2nBW0142p4szeZsBDrtO7pBdOhp7YeSZROFFlXZg== dependencies: "@0no-co/graphql.web" "^1.0.1" wonka "^6.3.2" @@ -3406,9 +3406,9 @@ accepts@^1.3.7, accepts@^1.3.8, accepts@~1.3.5, accepts@~1.3.7: negotiator "0.6.3" acorn@^8.8.2: - version "8.10.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" - integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== + version "8.11.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" + integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== agent-base@6: version "6.0.2" @@ -3592,12 +3592,12 @@ babel-plugin-polyfill-corejs2@^0.4.6: semver "^6.3.1" babel-plugin-polyfill-corejs3@^0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.5.tgz#a75fa1b0c3fc5bd6837f9ec465c0f48031b8cab1" - integrity sha512-Q6CdATeAvbScWPNLB8lzSO7fgUVBkQt6zLgNlfyeCr/EQaEQR+bWiBYYPYAFyE528BMjRhL+1QBMOI4jc/c5TA== + version "0.8.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.6.tgz#25c2d20002da91fe328ff89095c85a391d6856cf" + integrity sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ== dependencies: "@babel/helper-define-polyfill-provider" "^0.4.3" - core-js-compat "^3.32.2" + core-js-compat "^3.33.1" babel-plugin-polyfill-regenerator@^0.5.3: version "0.5.3" @@ -3865,12 +3865,13 @@ cacache@^15.3.0: unique-filename "^1.1.1" call-bind@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + version "1.0.5" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" + function-bind "^1.1.2" + get-intrinsic "^1.2.1" + set-function-length "^1.1.1" caller-callsite@^2.0.0: version "2.0.0" @@ -3902,9 +3903,9 @@ camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001541: - version "1.0.30001547" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001547.tgz#d4f92efc488aab3c7f92c738d3977c2a3180472b" - integrity sha512-W7CrtIModMAxobGhz8iXmDfuJiiKg1WADMO/9x7/CLNin5cpSbuBjooyoIUVB5eyCc36QuTVlkVa1iB2S5+/eA== + version "1.0.30001559" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz#95a982440d3d314c471db68d02664fb7536c5a30" + integrity sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA== chalk@^2.0.1, chalk@^2.4.2: version "2.4.2" @@ -4144,10 +4145,10 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -core-js-compat@^3.31.0, core-js-compat@^3.32.2: - version "3.33.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.33.0.tgz#24aa230b228406450b2277b7c8bfebae932df966" - integrity sha512-0w4LcLXsVEuNkIqwjjf9rjCoPhK8uqA4tMRh4Ge26vfLtUutshn+aRJU21I9LCJlh2QQHfisNToLjw1XEJLTWw== +core-js-compat@^3.31.0, core-js-compat@^3.33.1: + version "3.33.2" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.33.2.tgz#3ea4563bfd015ad4e4b52442865b02c62aba5085" + integrity sha512-axfo+wxFVxnqf8RvxTzoAlzW4gRoacrHeoFlc9n0x50+7BEyZL/Rt3hicaED1/CEd7I6tPCPVUYcJwCMO5XUYw== dependencies: browserslist "^4.22.1" @@ -4199,9 +4200,9 @@ crypt@0.0.2, crypt@~0.0.1: integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow== crypto-js@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" - integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== + version "4.2.0" + resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.2.0.tgz#4d931639ecdfd12ff80e8186dba6af2c2e856631" + integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q== crypto-random-string@^1.0.0: version "1.0.0" @@ -4315,6 +4316,15 @@ defaults@^1.0.3: dependencies: clone "^1.0.2" +define-data-property@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -4429,9 +4439,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== electron-to-chromium@^1.4.535: - version "1.4.554" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.554.tgz#04e09c2ee31dc0f1546174033809b54cc372740b" - integrity sha512-Q0umzPJjfBrrj8unkONTgbKQXzXRrH7sVV7D9ea2yBV3Oaogz991yhbpfvo2LMNkJItmruXTEzVpP9cp7vaIiQ== + version "1.4.572" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.572.tgz#ed9876658998138fe9e3aa47ecfa0bf914192a86" + integrity sha512-RlFobl4D3ieetbnR+2EpxdzFl9h0RAJkPK3pfiwMug2nhBin2ZCsGIAJWdpNniLz43sgXam/CgipOmvTA+rUiA== emoji-regex@^8.0.0: version "8.0.0" @@ -4461,9 +4471,9 @@ env-editor@^0.4.1: integrity sha512-ObFo8v4rQJAE59M69QzwloxPZtd33TpYEIjtKD1rrFDcM1Gd7IkDxEBU+HriziN6HSHQnBJi8Dmy+JWkav5HKA== envinfo@^7.7.2: - version "7.10.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.10.0.tgz#55146e3909cc5fe63c22da63fb15b05aeac35b13" - integrity sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw== + version "7.11.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.11.0.tgz#c3793f44284a55ff8c82faf1ffd91bc6478ea01f" + integrity sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg== eol@^0.9.1: version "0.9.1" @@ -4696,12 +4706,12 @@ expo-updates-interface@~0.10.0: integrity sha512-I6JMR7EgjXwckrydDmrkBEX/iw750dcqpzQVsjznYWfi0HTEOxajLHB90fBFqQkUV5i5s4Fd3hYQ1Cn0oMzUbA== expo@~49.0.13: - version "49.0.13" - resolved "https://registry.yarnpkg.com/expo/-/expo-49.0.13.tgz#9ee185d4eb1ac2859e67895bd919db5a04d1b8ec" - integrity sha512-k2QFmT5XN490ksjKJgogfS5SFj6ZKCu1GwWz4VUV4S9gkPjzr8zQAZoVPKaWxUYRb6xDpTJXdhLt7gSnV3bJvw== + version "49.0.16" + resolved "https://registry.yarnpkg.com/expo/-/expo-49.0.16.tgz#60399f25f141d649707cef928b90305057000923" + integrity sha512-1TcpWUEpzCQ7FjtwO1j+l/UvNgrEDZWfQm4kOo9eVZVDNKavYo+KL4XXHeljSAOOGhI/plmpD3bvhfYoywOAFQ== dependencies: "@babel/runtime" "^7.20.0" - "@expo/cli" "0.10.13" + "@expo/cli" "0.10.14" "@expo/config" "8.1.2" "@expo/config-plugins" "7.2.5" "@expo/vector-icons" "^13.0.0" @@ -4873,23 +4883,23 @@ find-yarn-workspace-root@~2.0.0: micromatch "^4.0.2" firebase@^10.5.0: - version "10.5.0" - resolved "https://registry.yarnpkg.com/firebase/-/firebase-10.5.0.tgz#bc04ff746b0e6a7bd2bc21b63eeb46eb68d61c9d" - integrity sha512-ROwoOFQa7tZret/giHtVJH4YCRLCuKpN386mxzXd0likAVmv+38YGkJiqfkmZju7dIQ+QJOvBScXVf27Kvob0g== + version "10.5.2" + resolved "https://registry.yarnpkg.com/firebase/-/firebase-10.5.2.tgz#c50d3c1e9026cad517913666eea8def2d25d4587" + integrity sha512-LLCig21TBYdByMbGJt5YmUzzk2HpsFCsIUTvOteQjW9BUh40IrSP2+dZi9IvT8RlztM3zcH+TNZ0jOsOaa7GMQ== dependencies: "@firebase/analytics" "0.10.0" "@firebase/analytics-compat" "0.2.6" - "@firebase/app" "0.9.20" + "@firebase/app" "0.9.22" "@firebase/app-check" "0.8.0" "@firebase/app-check-compat" "0.3.7" - "@firebase/app-compat" "0.2.20" + "@firebase/app-compat" "0.2.22" "@firebase/app-types" "0.9.0" - "@firebase/auth" "1.3.0" - "@firebase/auth-compat" "0.4.6" + "@firebase/auth" "1.3.2" + "@firebase/auth-compat" "0.4.8" "@firebase/database" "1.0.1" "@firebase/database-compat" "1.0.1" - "@firebase/firestore" "4.3.0" - "@firebase/firestore-compat" "0.3.19" + "@firebase/firestore" "4.3.2" + "@firebase/firestore-compat" "0.3.21" "@firebase/functions" "0.10.0" "@firebase/functions-compat" "0.3.5" "@firebase/installations" "0.6.4" @@ -4910,9 +4920,9 @@ flow-enums-runtime@^0.0.5: integrity sha512-PSZF9ZuaZD03sT9YaIs0FrGJ7lSUw7rHZIex+73UYVXg46eL/wxN5PaVcPJFudE2cJu5f0fezitV5aBkLHPUOQ== flow-parser@0.*: - version "0.218.1" - resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.218.1.tgz#a4a5d14c2cfd40dc76649b23f48fb4facd9156f9" - integrity sha512-46xpXyI4Bh3K2ej+NF3V5+pAsDlB5P0DWpgIIy/0/R7ujK0syfI/xfKDCOlq2sxtfUyPrr4rxfS2Da7yWdTdwg== + version "0.220.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.220.0.tgz#de184e9da22b47ead09cf40ab4e781a17149017d" + integrity sha512-Fks+nOCqhorp4NpAtAxf09UaR/9xDf3AnU1UkWczmpneoHh06Y3AoEA4tIe2HbYrOHT9JArUgDZpCFhP4clo1A== flow-parser@^0.206.0: version "0.206.0" @@ -5003,7 +5013,7 @@ fsevents@^2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1: +function-bind@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== @@ -5018,15 +5028,15 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" - integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" + integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== dependencies: - function-bind "^1.1.1" - has "^1.0.3" + function-bind "^1.1.2" has-proto "^1.0.1" has-symbols "^1.0.3" + hasown "^2.0.0" get-port@^3.2.0: version "3.2.0" @@ -5120,6 +5130,13 @@ globby@^11.0.1: merge2 "^1.4.1" slash "^3.0.0" +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + graceful-fs@^4.1.11, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" @@ -5147,6 +5164,13 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-property-descriptors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" + integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== + dependencies: + get-intrinsic "^1.2.2" + has-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" @@ -5157,10 +5181,12 @@ has-symbols@^1.0.3: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== -has@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" - integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" hermes-estree@0.12.0: version "0.12.0" @@ -5314,13 +5340,13 @@ internal-ip@4.3.0: ipaddr.js "^1.9.0" intl-messageformat@^10.1.0: - version "10.5.3" - resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.5.3.tgz#db0779d4a1988faa2977d76574489b7a25f0d5d0" - integrity sha512-TzKn1uhJBMyuKTO4zUX47SU+d66fu1W9tVzIiZrQ6hBqQQeYscBMIzKL/qEXnFbJrH9uU5VV3+T5fWib4SIcKA== + version "10.5.4" + resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.5.4.tgz#7b212b083f1b354d7e282518e78057e025134af9" + integrity sha512-z+hrFdiJ/heRYlzegrdFYqU1m/KOMOVMqNilIArj+PbsuU8TNE7v4TWdQgSoxlxbT4AcZH3Op3/Fu15QTp+W1w== dependencies: "@formatjs/ecma402-abstract" "1.17.2" "@formatjs/fast-memoize" "2.2.0" - "@formatjs/icu-messageformat-parser" "2.6.2" + "@formatjs/icu-messageformat-parser" "2.7.0" tslib "^2.4.0" invariant@*, invariant@^2.2.4: @@ -5356,11 +5382,11 @@ is-buffer@~1.1.1, is-buffer@~1.1.6: integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-core-module@^2.13.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db" - integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ== + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: - has "^1.0.3" + hasown "^2.0.0" is-directory@^0.3.1: version "0.3.1" @@ -6618,9 +6644,9 @@ object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== object-inspect@^1.9.0: - version "1.12.3" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" - integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== on-finished@2.4.1: version "2.4.1" @@ -7083,9 +7109,9 @@ rc@~1.2.7: strip-json-comments "~2.0.1" react-devtools-core@^4.27.2: - version "4.28.4" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.28.4.tgz#fb8183eada77093f4c2f9830e664bf22255abe27" - integrity sha512-IUZKLv3CimeM07G3vX4H4loxVpByrzq3HvfTX7v9migalwvLs9ZY5D3S3pKR33U+GguYfBBdMMZyToFhsSE/iQ== + version "4.28.5" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.28.5.tgz#c8442b91f068cdf0c899c543907f7f27d79c2508" + integrity sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA== dependencies: shell-quote "^1.6.1" ws "^7" @@ -7137,14 +7163,14 @@ react-native-responsive-screen@^1.4.2: integrity sha512-BLYz0UUpeohrib7jbz6wDmtBD5OmiuMRko4IT8kIF63taXPod/c5iZgmWnr5qOnK8hMuKiGMvsM3sC+eHX/lEQ== react-native-safe-area-context@^4.7.2: - version "4.7.2" - resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.7.2.tgz#1673aa99b6a9235e7faaf5a248e69795d6e54e07" - integrity sha512-5fy/hRNJ7bI/U2SliOeKf0D80J4lXPc1NsRiNS7Xaz8YTnqlzWib1ViItkwKPfufe54YKzVBMmM32RpdzvO2gg== + version "4.7.4" + resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.7.4.tgz#3dd8438971e70043d76f2428ede75b8a9639265e" + integrity sha512-3LR3DCq9pdzlbq6vsHGWBFehXAKDh2Ljug6jWhLWs1QFuJHM6AS2+mH2JfKlB2LqiSFZOBcZfHQFz0sGaA3uqg== react-native-screens@^3.25.0: - version "3.25.0" - resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.25.0.tgz#cf45e271ce733c9cf782fef8c9b3eb9e53faf01d" - integrity sha512-TSC2Ad0hh763I8QT6XxMsPXAagQ+RawDSdFtKRvIz9fCYr96AjRwwaqmYivbqlDywOgcRBkIVynkFtp0ThmlYw== + version "3.27.0" + resolved "https://registry.yarnpkg.com/react-native-screens/-/react-native-screens-3.27.0.tgz#2ac39f78dee27df97d3b6fb11ebf8e5751aa986a" + integrity sha512-FzSUygZ7yLQyhDJZsl7wU68LwRpVtVdqOPWribmEU3Tf26FohFGGcfJx1D8lf2V2Teb8tI+IaLnXCKbyh2xffA== dependencies: react-freeze "^1.0.0" warn-once "^0.1.0" @@ -7158,9 +7184,9 @@ react-native-svg@^13.14.0: css-tree "^1.1.3" react-native-vector-icons@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-10.0.0.tgz#0f031f7717f76f0a397f725de9b5a47ec87862e9" - integrity sha512-efMOVbZIebY8RszZPzPBoXi9pvD/NFYmjIDYxRoc9LYSzV8rMJtT8FfcO2hPu85Rn2x9xktha0+qn0B7EqMAcQ== + version "10.0.1" + resolved "https://registry.yarnpkg.com/react-native-vector-icons/-/react-native-vector-icons-10.0.1.tgz#ef5aa98034c5fb7cc45cd0c6ea5f37c74ce4c44b" + integrity sha512-oqVyhSgK1wLm7JuN5yep+BCWb4F4C6qi2/mHGsdNqneGWn3MI9VVMX+AIkw0q9GsbY6QjhNd5sUanjRyDJfuUg== dependencies: prop-types "^15.7.2" yargs "^16.1.1" @@ -7547,6 +7573,16 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-function-length@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== + dependencies: + define-data-property "^1.1.1" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -7918,9 +7954,9 @@ terminal-link@^2.1.1: supports-hyperlinks "^2.0.0" terser@^5.15.0: - version "5.21.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.21.0.tgz#d2b27e92b5e56650bc83b6defa00a110f0b124b2" - integrity sha512-WtnFKrxu9kaoXuiZFSGrcAvvBqAdmKx0SFNmVNYdJamMu9yyN3I/QF0FbH4QcqJQ+y1CJnzxGIKH0cSj+FGYRw== + version "5.24.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.24.0.tgz#4ae50302977bca4831ccc7b4fef63a3c04228364" + integrity sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -8062,9 +8098,9 @@ typescript@^5.1.3: integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== ua-parser-js@^1.0.35: - version "1.0.36" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.36.tgz#a9ab6b9bd3a8efb90bb0816674b412717b7c428c" - integrity sha512-znuyCIXzl8ciS3+y3fHJI/2OhQIXbXw9MWC/o3qwyR+RGppjZHrM27CGFSKCJXi2Kctiz537iOu2KnXs1lMQhw== + version "1.0.37" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.37.tgz#b5dc7b163a5c1f0c510b08446aed4da92c46373f" + integrity sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ== uglify-es@^3.1.9: version "3.3.9" @@ -8074,10 +8110,10 @@ uglify-es@^3.1.9: commander "~2.13.0" source-map "~0.6.1" -undici-types@~5.25.1: - version "5.25.3" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.25.3.tgz#e044115914c85f0bcbb229f346ab739f064998c3" - integrity sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" @@ -8179,10 +8215,10 @@ url@^0.11.0: punycode "^1.4.1" qs "^6.11.2" -use-latest-callback@^0.1.5: - version "0.1.6" - resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.1.6.tgz#3fa6e7babbb5f9bfa24b5094b22939e1e92ebcf6" - integrity sha512-VO/P91A/PmKH9bcN9a7O3duSuxe6M14ZoYXgA6a8dab8doWNdhiIHzEkX/jFeTTRBsX0Ubk6nG4q2NIjNsj+bg== +use-latest-callback@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.1.7.tgz#f189fa4e58ee18c7a2d9de53f92210e118d1b14f" + integrity sha512-Hlrl0lskgZZpo2vIpZ4rA7qA/rAGn2PcDvDH1M47AogqMPB0qlGEdsa66AVkIUiEEDpfxA9/N6hY6MqtaNoqWA== use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.0: version "1.2.0" @@ -8422,9 +8458,9 @@ yallist@^4.0.0: integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yaml@^2.2.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.2.tgz#f522db4313c671a0ca963a75670f1c12ea909144" - integrity sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg== + version "2.3.3" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.3.tgz#01f6d18ef036446340007db8e016810e5d64aad9" + integrity sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ== yargs-parser@^18.1.2: version "18.1.3" From 4bd73373cbae81a32f9a0b2982750aadb19274bd Mon Sep 17 00:00:00 2001 From: David Oduneye Date: Wed, 1 Nov 2023 19:24:18 -0400 Subject: [PATCH 6/6] style: formatting --- server/src/controllers/profile.go | 5 +++++ server/src/models/profile.go | 13 +++++++------ server/src/services/profile.go | 1 + server/src/types/OnboardingResponse.go | 1 + 4 files changed, 14 insertions(+), 6 deletions(-) diff --git a/server/src/controllers/profile.go b/server/src/controllers/profile.go index de8963c..75ff328 100644 --- a/server/src/controllers/profile.go +++ b/server/src/controllers/profile.go @@ -68,6 +68,11 @@ func (p *ProfileController) InsertOnboardingResponse(c echo.Context) error { return c.JSON(http.StatusBadRequest, "Failed to process the request") } + // 1. Get Score + // 2. Remove it from struct + // 3. Calculate Score to determine persona + // 4. Insert persona into user + // 5. Return user profile, err := p.profileService.InsertOnboardingResponse(profileID, onboardingResponse, profile) if err != nil { return c.JSON(http.StatusInternalServerError, "Failed to insert onboarding response") diff --git a/server/src/models/profile.go b/server/src/models/profile.go index 798ef9c..c9d3eed 100644 --- a/server/src/models/profile.go +++ b/server/src/models/profile.go @@ -8,10 +8,11 @@ import ( type Profile struct { gorm.Model - Name string `gorm:"type:varchar(255)" json:"name" validate:"required"` - DateOfBirth time.Time `gorm:"type:date" json:"date_of_birth" validate:"required"` - PhoneNumber string `gorm:"type:varchar(20)" json:"phone_number" validate:"required"` - OnboardingResponse string `gorm:"type:jsonb;default:'{}'" json:"response"` - UserID uint `gorm:"foreignkey:User;unique" json:"user_id"` - User *User `json:"-"` + Name string `gorm:"type:varchar(255)" json:"name" validate:"required"` + DateOfBirth time.Time `gorm:"type:date" json:"date_of_birth" validate:"required"` + PhoneNumber string `gorm:"type:varchar(20)" json:"phone_number" validate:"required"` + OnboardingResponse string `gorm:"type:jsonb;default:'{}'" json:"response"` + CompletedOnboardingResponse bool `gorm:"type:boolean;default:false" json:"completed_onboarding_response"` + UserID uint `gorm:"foreignkey:User;unique" json:"user_id"` + User *User `json:"-"` } diff --git a/server/src/services/profile.go b/server/src/services/profile.go index 0399008..35b53f4 100644 --- a/server/src/services/profile.go +++ b/server/src/services/profile.go @@ -72,6 +72,7 @@ func (p *ProfileService) InsertOnboardingResponse(id string, onboardingResponse // Update the OnboardingResponse field of the user profile profile.OnboardingResponse = string(response) + profile.CompletedOnboardingResponse = true // Update the user profile with the new onboarding response profile, err = p.UpdateProfile(id, profile) diff --git a/server/src/types/OnboardingResponse.go b/server/src/types/OnboardingResponse.go index 1f2276e..fb07585 100644 --- a/server/src/types/OnboardingResponse.go +++ b/server/src/types/OnboardingResponse.go @@ -19,4 +19,5 @@ type OnboardingResponse struct { SocialInclinationQ3 string `json:"socialInclinationQ3"` FunnelActivitiesQ1 string `json:"funnelActivitiesQ1"` FunnelActivitiesQ2 string `json:"funnelActivitiesQ2"` + Score int `json:"score"` }