Compare commits
2 Commits
3177a4d089
...
f66a990040
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f66a990040 | ||
|
|
983d326a47 |
@ -39,7 +39,6 @@ func (s *Server) GoogleCallbackHandlerV2(ctx *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BUG: This is not working, not yet sure why
|
|
||||||
func (s *Server) LogoutHandlerV2(ctx *gin.Context) {
|
func (s *Server) LogoutHandlerV2(ctx *gin.Context) {
|
||||||
s.SetCookie(ctx, "jwt_token", "", -1)
|
s.SetCookie(ctx, "jwt_token", "", -1)
|
||||||
// s.SetCookie(ctx, "search-filters", "", -1) // TODO: This was copied, might function differently now
|
// s.SetCookie(ctx, "search-filters", "", -1) // TODO: This was copied, might function differently now
|
||||||
|
|||||||
@ -20,7 +20,7 @@ func (s *Server) SetCookie(ctx *gin.Context, name, value string, duration time.D
|
|||||||
path string = "/"
|
path string = "/"
|
||||||
httpOnly bool = false // NOTE: Should use false so React can see it!
|
httpOnly bool = false // NOTE: Should use false so React can see it!
|
||||||
maxAge int
|
maxAge int
|
||||||
secure bool = false
|
secure bool = false
|
||||||
domain string = ""
|
domain string = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -207,6 +207,8 @@ func (s *Server) Setup() *Server {
|
|||||||
router_api_v2.GET("/auth/logout", s.LogoutHandlerV2)
|
router_api_v2.GET("/auth/logout", s.LogoutHandlerV2)
|
||||||
|
|
||||||
router_api_v2.GET("/user", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenticatedUserHandlerV2)
|
router_api_v2.GET("/user", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenticatedUserHandlerV2)
|
||||||
|
router_api_v2.GET("/user/recipes", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenicatedUserRecipesV2)
|
||||||
|
router_api_v2.GET("/user/favorites", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenicatedUserFavoritesV2)
|
||||||
|
|
||||||
router_api_v2.GET("/protected", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), func(ctx *gin.Context) {
|
router_api_v2.GET("/protected", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), func(ctx *gin.Context) {
|
||||||
ctx.JSON(http.StatusOK, gin.H{"msg": "YAY"})
|
ctx.JSON(http.StatusOK, gin.H{"msg": "YAY"})
|
||||||
|
|||||||
@ -1,25 +1,77 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func (s *Server) GetAuthenticatedUserHandlerV2(ctx *gin.Context) {
|
func (s *Server) GetAuthenticatedUserHandlerV2(ctx *gin.Context) {
|
||||||
user := s.deps.UserService.GetAuthenicatedUser(ctx)
|
user := s.deps.UserService.GetAuthenicatedUser(ctx)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
ctx.JSON(http.StatusUnauthorized, gin.H{
|
ctx.JSON(http.StatusUnauthorized, gin.H{
|
||||||
"status": http.StatusUnauthorized,
|
"status": http.StatusUnauthorized,
|
||||||
"message": "[UNAUTHORIZED] Could not fetch authenticated user.",
|
"message": "[UNAUTHORIZED] Could not fetch authenticated user.",
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, gin.H{
|
ctx.JSON(http.StatusOK, gin.H{
|
||||||
"status": http.StatusOK,
|
"status": http.StatusOK,
|
||||||
"message": "[OK] Successfully retrieved authenticated user.",
|
"message": "[OK] Successfully retrieved authenticated user.",
|
||||||
"user": user,
|
"user": user,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetAuthenicatedUserRecipesV2(ctx *gin.Context) {
|
||||||
|
user := s.deps.UserService.GetAuthenicatedUser(ctx)
|
||||||
|
if user == nil {
|
||||||
|
ctx.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"status": http.StatusUnauthorized,
|
||||||
|
"message": "[UNAUTHORIZED] Could not fetch authenticated user.",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
recipes, err := s.deps.RecipeService.GetUserRecipes(user.Id)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"status": http.StatusBadRequest,
|
||||||
|
"message": fmt.Sprintf("[FAILED] Could not fetch authenticated users's recipes. %s", err.Error()),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, gin.H{
|
||||||
|
"status": http.StatusOK,
|
||||||
|
"message": "[OK] Successfully retrieved authenticated user's recipes.",
|
||||||
|
"recipes": recipes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) GetAuthenicatedUserFavoritesV2(ctx *gin.Context) {
|
||||||
|
user := s.deps.UserService.GetAuthenicatedUser(ctx)
|
||||||
|
if user == nil {
|
||||||
|
ctx.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"status": http.StatusUnauthorized,
|
||||||
|
"message": "[UNAUTHORIZED] Could not fetch authenticated user.",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
favorites, err := s.deps.RecipeService.GetUserFavoriteRecipes(user.Id)
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||||
|
"status": http.StatusBadRequest,
|
||||||
|
"message": fmt.Sprintf("[FAILED] Could not fetch authenticated users's favorites. %s", err.Error()),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, gin.H{
|
||||||
|
"status": http.StatusOK,
|
||||||
|
"message": "[OK] Successfully retrieved authenticated user's favorites.",
|
||||||
|
"favorites": favorites,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,9 +5,9 @@ import "time"
|
|||||||
// RecipeDuration is the duration to prepare recipe. It has JSON tags which allows it to be
|
// RecipeDuration is the duration to prepare recipe. It has JSON tags which allows it to be
|
||||||
// marshaled into a JSON object and stored in the database (JSONB).
|
// marshaled into a JSON object and stored in the database (JSONB).
|
||||||
type RecipeDuration struct {
|
type RecipeDuration struct {
|
||||||
Total int `json:"total"`
|
Total int `json:"Total"`
|
||||||
Prep int `json:"prep"`
|
Prep int `json:"Prep"`
|
||||||
Cook int `json:"cook"`
|
Cook int `json:"Cook"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecipeMeal is the database enum E_MEAL which defines the meal type of a recipe. Postgres enums
|
// RecipeMeal is the database enum E_MEAL which defines the meal type of a recipe. Postgres enums
|
||||||
@ -49,8 +49,8 @@ func ParseMeal(meal int) RecipeMeal {
|
|||||||
// RecipeIngredient is a single ingredients in a recipe. These have JSON tags which allow them
|
// RecipeIngredient is a single ingredients in a recipe. These have JSON tags which allow them
|
||||||
// to be marshaled into a JSON array and stored in the database (JSONB).
|
// to be marshaled into a JSON array and stored in the database (JSONB).
|
||||||
type RecipeIngredient struct {
|
type RecipeIngredient struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"Name"`
|
||||||
Quantity string `json:"quantity"`
|
Quantity string `json:"Quantity"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recipe is the database model of a recipe. There is no need to map to a different model so
|
// Recipe is the database model of a recipe. There is no need to map to a different model so
|
||||||
|
|||||||
@ -38,8 +38,8 @@ type InjectedDependencies struct {
|
|||||||
// JwtClaims is the data stored in the JSON web token. All that is needed is the users ID and their
|
// JwtClaims is the data stored in the JSON web token. All that is needed is the users ID and their
|
||||||
// Google email provided.
|
// Google email provided.
|
||||||
type JwtClaims struct {
|
type JwtClaims struct {
|
||||||
UserId int `json:"id"`
|
UserId int `json:"Id"`
|
||||||
Email string `json:"email"`
|
Email string `json:"Email"`
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,13 +4,13 @@ import "time"
|
|||||||
|
|
||||||
// GoogleUserInfo is a data type which contains a mapping of the Google User Info API call.
|
// GoogleUserInfo is a data type which contains a mapping of the Google User Info API call.
|
||||||
type GoogleUserInfo struct {
|
type GoogleUserInfo struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"Id"`
|
||||||
Email string `json:"email"`
|
Email string `json:"Email"`
|
||||||
Verified bool `json:"verified_email"`
|
Verified bool `json:"VerifiedEmail"`
|
||||||
Name string `json:"name"`
|
Name string `json:"Name"`
|
||||||
GivenName string `json:"given_name"`
|
GivenName string `json:"GivenName"`
|
||||||
FamilyName string `json:"family_name"`
|
FamilyName string `json:"FamilyName"`
|
||||||
Picture string `json:"picture"`
|
Picture string `json:"Picture"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// User is the database model of a user. There is no need to map to a different model so
|
// User is the database model of a user. There is no need to map to a different model so
|
||||||
|
|||||||
@ -4,6 +4,10 @@ import './index.css'
|
|||||||
import App from './App.tsx'
|
import App from './App.tsx'
|
||||||
import { AuthProvider } from './context/AuthProvider.tsx'
|
import { AuthProvider } from './context/AuthProvider.tsx'
|
||||||
import { CookiesProvider } from 'react-cookie'
|
import { CookiesProvider } from 'react-cookie'
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
// Set the with 'withCredentials' by default
|
||||||
|
axios.defaults.withCredentials = true;
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import RecipeListItem from "../components/results/RecipeListItem";
|
|||||||
import type { Engagement } from "../types/engagement";
|
import type { Engagement } from "../types/engagement";
|
||||||
import ActivityListItem from "../components/results/ActivityListItem";
|
import ActivityListItem from "../components/results/ActivityListItem";
|
||||||
import { AuthContext } from "../context/AuthContext";
|
import { AuthContext } from "../context/AuthContext";
|
||||||
import { GetAuthenticatedUser } from "../services/UserService";
|
import { GetAuthenticatedUser, GetAuthenticatedUserFavorites, GetAuthenticatedUserRecipes } from "../services/UserService";
|
||||||
import { isApiError, type ApiError } from "../types/api/error";
|
import { isApiError, type ApiError } from "../types/api/error";
|
||||||
import { Logout } from "../services/AuthService";
|
import { Logout } from "../services/AuthService";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
@ -25,84 +25,6 @@ export default function Profile() {
|
|||||||
|
|
||||||
// BUG: Remove this, used for testing
|
// BUG: Remove this, used for testing
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const recipe: Recipe = {
|
|
||||||
Id: 1,
|
|
||||||
Title: "Classic Pancakes",
|
|
||||||
Description: "Fluffy and delicious pancakes perfect for breakfast.",
|
|
||||||
Instructions: [
|
|
||||||
"In a bowl, mix all the dry ingredients.",
|
|
||||||
"In another bowl, whisk the wet ingredients.",
|
|
||||||
"Combine both mixes until smooth.",
|
|
||||||
"Heat a non-stick skillet and pour batter.",
|
|
||||||
"Cook until bubbles form, flip and cook the other side.",
|
|
||||||
"Serve warm with syrup."
|
|
||||||
],
|
|
||||||
Serves: 4,
|
|
||||||
Difficulty: 2, // scale 1-5 (example)
|
|
||||||
Duration: {
|
|
||||||
Total: 20,
|
|
||||||
Prep: 5,
|
|
||||||
Cook: 15
|
|
||||||
},
|
|
||||||
Category: "breakfast",
|
|
||||||
Ingredients: [
|
|
||||||
{ Name: "Flour", Quantity: "2 cups" },
|
|
||||||
{ Name: "Milk", Quantity: "1.5 cups" },
|
|
||||||
{ Name: "Egg", Quantity: "1 large" },
|
|
||||||
{ Name: "Baking Powder", Quantity: "2 teaspoons" },
|
|
||||||
{ Name: "Salt", Quantity: "0.5 teaspoon" },
|
|
||||||
{ Name: "Sugar", Quantity: "1 tablespoon" }
|
|
||||||
],
|
|
||||||
UserId: 101,
|
|
||||||
Modified: new Date("2025-10-30T09:00:00"),
|
|
||||||
Created: new Date("2025-10-01T08:30:00"),
|
|
||||||
Tags: [
|
|
||||||
{ Id: 1, Name: "easy", Created: new Date("2025-01-01T12:00:00") },
|
|
||||||
{ Id: 2, Name: "quick", Created: new Date("2025-01-02T12:00:00") },
|
|
||||||
{ Id: 3, Name: "breakfast", Created: new Date("2025-01-03T12:00:00") }
|
|
||||||
],
|
|
||||||
Favorite: true
|
|
||||||
};
|
|
||||||
|
|
||||||
const recipe2: Recipe = {
|
|
||||||
Id: 2,
|
|
||||||
Title: "Classic Pancakes",
|
|
||||||
Description: "Fluffy and delicious pancakes perfect for breakfast.",
|
|
||||||
Instructions: [
|
|
||||||
"In a bowl, mix all the dry ingredients.",
|
|
||||||
"In another bowl, whisk the wet ingredients.",
|
|
||||||
"Combine both mixes until smooth.",
|
|
||||||
"Heat a non-stick skillet and pour batter.",
|
|
||||||
"Cook until bubbles form, flip and cook the other side.",
|
|
||||||
"Serve warm with syrup."
|
|
||||||
],
|
|
||||||
Serves: 4,
|
|
||||||
Difficulty: 2, // scale 1-5 (example)
|
|
||||||
Duration: {
|
|
||||||
Total: 20,
|
|
||||||
Prep: 5,
|
|
||||||
Cook: 15
|
|
||||||
},
|
|
||||||
Category: "breakfast",
|
|
||||||
Ingredients: [
|
|
||||||
{ Name: "Flour", Quantity: "2 cups" },
|
|
||||||
{ Name: "Milk", Quantity: "1.5 cups" },
|
|
||||||
{ Name: "Egg", Quantity: "1 large" },
|
|
||||||
{ Name: "Baking Powder", Quantity: "2 teaspoons" },
|
|
||||||
{ Name: "Salt", Quantity: "0.5 teaspoon" },
|
|
||||||
{ Name: "Sugar", Quantity: "1 tablespoon" }
|
|
||||||
],
|
|
||||||
UserId: 101,
|
|
||||||
Modified: new Date("2025-10-30T09:00:00"),
|
|
||||||
Created: new Date("2025-10-01T08:30:00"),
|
|
||||||
Tags: [
|
|
||||||
{ Id: 1, Name: "easy", Created: new Date("2025-01-01T12:00:00") },
|
|
||||||
{ Id: 2, Name: "quick", Created: new Date("2025-01-02T12:00:00") },
|
|
||||||
{ Id: 3, Name: "breakfast", Created: new Date("2025-01-03T12:00:00") }
|
|
||||||
],
|
|
||||||
Favorite: true
|
|
||||||
};
|
|
||||||
|
|
||||||
const eng: Engagement = {
|
const eng: Engagement = {
|
||||||
Id: 1,
|
Id: 1,
|
||||||
Type: "made",
|
Type: "made",
|
||||||
@ -112,8 +34,6 @@ export default function Profile() {
|
|||||||
Created: new Date(),
|
Created: new Date(),
|
||||||
};
|
};
|
||||||
|
|
||||||
setRecipes([recipe, recipe2]);
|
|
||||||
setFavorites([recipe, recipe2]);
|
|
||||||
setActivity([eng]);
|
setActivity([eng]);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -123,6 +43,29 @@ export default function Profile() {
|
|||||||
void navigate("/v2/web/home");
|
void navigate("/v2/web/home");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fetchProfileData = async (): Promise<void> => {
|
||||||
|
const result_user: User | ApiError = await GetAuthenticatedUser();
|
||||||
|
if (isApiError(result_user)) {
|
||||||
|
setError(result_user.message);
|
||||||
|
} else {
|
||||||
|
setUser(result_user);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result_recipes: Recipe[] | ApiError = await GetAuthenticatedUserRecipes();
|
||||||
|
if (isApiError(result_recipes)) {
|
||||||
|
setError(result_recipes.message);
|
||||||
|
} else {
|
||||||
|
setRecipes(result_recipes);
|
||||||
|
}
|
||||||
|
|
||||||
|
const result_favorites: Recipe[] | ApiError = await GetAuthenticatedUserFavorites();
|
||||||
|
if (isApiError(result_favorites)) {
|
||||||
|
setError(result_favorites.message);
|
||||||
|
} else {
|
||||||
|
setFavorites(result_favorites);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get the JWT from the cookies
|
// Get the JWT from the cookies
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setJwt(getJwt());
|
setJwt(getJwt());
|
||||||
@ -130,18 +73,9 @@ export default function Profile() {
|
|||||||
|
|
||||||
// Get the user when the JWTS change
|
// Get the user when the JWTS change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// No jwt, we can't get a user
|
// No jwt, we can't get user data
|
||||||
if (!jwt) return;
|
if (jwt)
|
||||||
|
void fetchProfileData();
|
||||||
async function fetch() {
|
|
||||||
const result: User | ApiError = await GetAuthenticatedUser();
|
|
||||||
if (isApiError(result)) {
|
|
||||||
setError(result.message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setUser(result);
|
|
||||||
}
|
|
||||||
void fetch();
|
|
||||||
}, [jwt]);
|
}, [jwt]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -157,7 +91,7 @@ export default function Profile() {
|
|||||||
{user?.ImageUrl != "" ? (
|
{user?.ImageUrl != "" ? (
|
||||||
<img
|
<img
|
||||||
className="w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none"
|
className="w-24 md:w-32 border-2 border-blue-500 rounded-full shadow-blue-500 shadow select-none"
|
||||||
src={user?.ImageUrl ?? ""}
|
src={user?.ImageUrl ?? undefined}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<img
|
<img
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import type { GetGoogleAuthUrlResponse, LogoutResponse } from "../types/api/auth
|
|||||||
import type { ApiError } from "../types/api/error";
|
import type { ApiError } from "../types/api/error";
|
||||||
|
|
||||||
|
|
||||||
export async function GetGoogleAuthUrl (): Promise<string | ApiError> {
|
export async function GetGoogleAuthUrl(): Promise<string | ApiError> {
|
||||||
const response = await axios.get<GetGoogleAuthUrlResponse>("http://localhost:3000/v2/api/auth/login");
|
const response = await axios.get<GetGoogleAuthUrlResponse>("http://localhost:3000/v2/api/auth/login");
|
||||||
|
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
@ -17,7 +17,7 @@ export async function GetGoogleAuthUrl (): Promise<string | ApiError> {
|
|||||||
return response.data.url;
|
return response.data.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function Logout (): Promise<void> {
|
export async function Logout(): Promise<void> {
|
||||||
const response = await axios.get<LogoutResponse>("http://localhost:3000/v2/api/auth/logout");
|
const response = await axios.get<LogoutResponse>("http://localhost:3000/v2/api/auth/logout");
|
||||||
|
|
||||||
// This should never happen
|
// This should never happen
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import type { ApiError } from "../types/api/error";
|
import type { ApiError } from "../types/api/error";
|
||||||
import type { User } from "../types/user";
|
import type { User } from "../types/user";
|
||||||
import type { GetAuthenticateUserResponse } from "../types/api/user";
|
import type { GetAuthenticateUserFavoritesResponse, GetAuthenticateUserRecipesResponse, GetAuthenticateUserResponse } from "../types/api/user";
|
||||||
|
import type { Recipe } from "../types/recipe";
|
||||||
|
|
||||||
|
|
||||||
export async function GetAuthenticatedUser(): Promise<User | ApiError> {
|
export async function GetAuthenticatedUser(): Promise<User | ApiError> {
|
||||||
const response = await axios.get<GetAuthenticateUserResponse>("http://localhost:3000/v2/api/user", { withCredentials: true });
|
const response = await axios.get<GetAuthenticateUserResponse>("http://localhost:3000/v2/api/user");
|
||||||
|
|
||||||
if (response.data.status !== 200 || response.data.user === undefined){
|
if (response.data.status !== 200 || response.data.user === undefined) {
|
||||||
const err: ApiError = {
|
const err: ApiError = {
|
||||||
status: response.data.status,
|
status: response.data.status,
|
||||||
message: response.data.message
|
message: response.data.message
|
||||||
@ -17,3 +18,31 @@ export async function GetAuthenticatedUser(): Promise<User | ApiError> {
|
|||||||
|
|
||||||
return response.data.user;
|
return response.data.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function GetAuthenticatedUserRecipes(): Promise<Recipe[] | ApiError> {
|
||||||
|
const response = await axios.get<GetAuthenticateUserRecipesResponse>("http://localhost:3000/v2/api/user/recipes");
|
||||||
|
|
||||||
|
if (response.data.status !== 200 || response.data.recipes === undefined) {
|
||||||
|
const err: ApiError = {
|
||||||
|
status: response.data.status,
|
||||||
|
message: response.data.message
|
||||||
|
};
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.data.recipes;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetAuthenticatedUserFavorites(): Promise<Recipe[] | ApiError> {
|
||||||
|
const response = await axios.get<GetAuthenticateUserFavoritesResponse>("http://localhost:3000/v2/api/user/favorites");
|
||||||
|
|
||||||
|
if (response.data.status !== 200 || response.data.favorites === undefined) {
|
||||||
|
const err: ApiError = {
|
||||||
|
status: response.data.status,
|
||||||
|
message: response.data.message
|
||||||
|
};
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.data.favorites;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import type { Recipe } from "../recipe";
|
||||||
import type { User } from "../user";
|
import type { User } from "../user";
|
||||||
|
|
||||||
export interface GetAuthenticateUserResponse {
|
export interface GetAuthenticateUserResponse {
|
||||||
@ -5,3 +6,15 @@ export interface GetAuthenticateUserResponse {
|
|||||||
message: string;
|
message: string;
|
||||||
user?: User;
|
user?: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GetAuthenticateUserRecipesResponse {
|
||||||
|
status: number;
|
||||||
|
message: string;
|
||||||
|
recipes?: Recipe[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetAuthenticateUserFavoritesResponse {
|
||||||
|
status: number;
|
||||||
|
message: string;
|
||||||
|
favorites?: Recipe[];
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user