Merging in the React Refactor #56
@ -209,6 +209,7 @@ func (s *Server) Setup() *Server {
|
||||
router_api_v2.GET("/auth/logout", s.LogoutHandlerV2)
|
||||
|
||||
router_api_v2.GET("/user", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenticatedUserHandlerV2)
|
||||
router_api_v2.GET("/user/:id", s.GetUserV2)
|
||||
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("/user/engagement", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenicatedUserEngagementV2)
|
||||
|
||||
@ -3,11 +3,39 @@ package server
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
domain "github.com/haydenhargreaves/Potion/internal/domain/user"
|
||||
)
|
||||
|
||||
func (s *Server) GetUserV2(ctx *gin.Context) {
|
||||
id := ctx.Param("id")
|
||||
parsedId, err := strconv.Atoi(id)
|
||||
if err != nil {
|
||||
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||
"status": http.StatusBadRequest,
|
||||
"message": fmt.Sprintf("[ERROR] Failed to parse ID parameter. %s", err.Error()),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
user, err := s.deps.UserService.GetUser(parsedId)
|
||||
if err != nil {
|
||||
ctx.JSON(http.StatusBadRequest, gin.H{
|
||||
"status": http.StatusBadRequest,
|
||||
"message": fmt.Sprintf("[ERROR] Failed to get the target user. %s", err.Error()),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, gin.H{
|
||||
"status": http.StatusOK,
|
||||
"message": "[OK] Successfully retrieved target user.",
|
||||
"user": user,
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Server) GetAuthenticatedUserHandlerV2(ctx *gin.Context) {
|
||||
s.withAuthenticatedUser(ctx, func(ctx *gin.Context, user *domain.User) {
|
||||
ctx.JSON(http.StatusOK, gin.H{
|
||||
|
||||
@ -13,7 +13,6 @@ interface FavoriteButtonProps {
|
||||
export default function FavoriteButton({ favorite, id }: FavoriteButtonProps) {
|
||||
// CONTEXT
|
||||
const { isLoggedIn } = use(AuthContext);
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [_favorite, setFavorite] = useState<boolean>();
|
||||
|
||||
@ -13,6 +13,8 @@ import TagList from "../components/items/TagList";
|
||||
import IngredientList from "../components/items/IngredientList";
|
||||
import InstructionList from "../components/items/InstructionList";
|
||||
import Spinner from "../components/Spinner";
|
||||
import { GetUser } from "../services/UserService";
|
||||
import type { User } from "../types/user";
|
||||
|
||||
export default function RecipePage() {
|
||||
// Url params
|
||||
@ -20,6 +22,7 @@ export default function RecipePage() {
|
||||
|
||||
// Page state
|
||||
const [recipe, setRecipe] = useState<Recipe | null>(null);
|
||||
const [author, setAuthor] = useState<User | null>(null);
|
||||
const [error, setError] = useState<string>("");
|
||||
|
||||
useEffect(() => {
|
||||
@ -34,6 +37,20 @@ export default function RecipePage() {
|
||||
void fetch();
|
||||
}, [id]);
|
||||
|
||||
useEffect(() => {
|
||||
async function fetch() {
|
||||
if (!recipe) return;
|
||||
|
||||
const result: User | ApiError = await GetUser(recipe.UserId);
|
||||
if (isApiError(result)) {
|
||||
setError(result.message);
|
||||
} else {
|
||||
setAuthor(result);
|
||||
}
|
||||
}
|
||||
void fetch();
|
||||
}, [recipe]);
|
||||
|
||||
// BUG: Prob remove
|
||||
useEffect(() => {
|
||||
if (error)
|
||||
@ -45,7 +62,7 @@ export default function RecipePage() {
|
||||
<img className="bg-gray-100 w-full h-96 mx-auto mb-8" src={RecipePlaceholder} />
|
||||
<div className="px-4 py-8 md:px-8">
|
||||
<h1 className="text-3xl md:text-4xl font-bold text-gray-800">{recipe.Title}</h1>
|
||||
<p className="text-sm mt-2 mb-1 text-gray-700">Author: loading...</p>
|
||||
<p className="text-sm mt-2 mb-1 text-gray-700">{author ? author.Name : "Loading..."}</p>
|
||||
<p className="text-sm mb-2 text-gray-700">Category: {recipe.Category}</p>
|
||||
</div>
|
||||
<RecipeMetaData recipe={recipe} />
|
||||
|
||||
@ -1,10 +1,23 @@
|
||||
import axios from "axios";
|
||||
import type { ApiError } from "../types/api/error";
|
||||
import type { User } from "../types/user";
|
||||
import type { GetAuthenticateUserEngagementResponse, GetAuthenticateUserFavoritesResponse, GetAuthenticateUserMadeRecipesResponse, GetAuthenticateUserRecipesResponse, GetAuthenticateUserResponse, GetAuthenticateUserViewedRecipesResponse } from "../types/api/user";
|
||||
import type { GetAuthenticateUserEngagementResponse, GetAuthenticateUserFavoritesResponse, GetAuthenticateUserMadeRecipesResponse, GetAuthenticateUserRecipesResponse, GetAuthenticateUserResponse, GetAuthenticateUserViewedRecipesResponse, GetUserResponse } from "../types/api/user";
|
||||
import type { Recipe } from "../types/recipe";
|
||||
import type { Engagement } from "../types/engagement";
|
||||
|
||||
export async function GetUser(id: number): Promise<User | ApiError> {
|
||||
const response = await axios.get<GetUserResponse>(`http://localhost:3000/v2/api/user/${id}`);
|
||||
|
||||
if (response.data.status !== 200 || response.data.user === undefined) {
|
||||
const err: ApiError = {
|
||||
status: response.data.status,
|
||||
message: response.data.message
|
||||
};
|
||||
return err;
|
||||
}
|
||||
|
||||
return response.data.user;
|
||||
}
|
||||
|
||||
export async function GetAuthenticatedUser(): Promise<User | ApiError> {
|
||||
const response = await axios.get<GetAuthenticateUserResponse>("http://localhost:3000/v2/api/user");
|
||||
|
||||
@ -2,6 +2,12 @@ import type { Engagement } from "../engagement";
|
||||
import type { Recipe } from "../recipe";
|
||||
import type { User } from "../user";
|
||||
|
||||
export interface GetUserResponse {
|
||||
status: number;
|
||||
message: string;
|
||||
user?: User;
|
||||
}
|
||||
|
||||
export interface GetAuthenticateUserResponse {
|
||||
status: number;
|
||||
message: string;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user