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("/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/:id", s.GetUserV2)
|
||||||
router_api_v2.GET("/user/recipes", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenicatedUserRecipesV2)
|
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/favorites", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenicatedUserFavoritesV2)
|
||||||
router_api_v2.GET("/user/engagement", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenicatedUserEngagementV2)
|
router_api_v2.GET("/user/engagement", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenicatedUserEngagementV2)
|
||||||
|
|||||||
@ -3,11 +3,39 @@ package server
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
domain "github.com/haydenhargreaves/Potion/internal/domain/user"
|
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) {
|
func (s *Server) GetAuthenticatedUserHandlerV2(ctx *gin.Context) {
|
||||||
s.withAuthenticatedUser(ctx, func(ctx *gin.Context, user *domain.User) {
|
s.withAuthenticatedUser(ctx, func(ctx *gin.Context, user *domain.User) {
|
||||||
ctx.JSON(http.StatusOK, gin.H{
|
ctx.JSON(http.StatusOK, gin.H{
|
||||||
|
|||||||
@ -13,7 +13,6 @@ interface FavoriteButtonProps {
|
|||||||
export default function FavoriteButton({ favorite, id }: FavoriteButtonProps) {
|
export default function FavoriteButton({ favorite, id }: FavoriteButtonProps) {
|
||||||
// CONTEXT
|
// CONTEXT
|
||||||
const { isLoggedIn } = use(AuthContext);
|
const { isLoggedIn } = use(AuthContext);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const [_favorite, setFavorite] = useState<boolean>();
|
const [_favorite, setFavorite] = useState<boolean>();
|
||||||
|
|||||||
@ -13,6 +13,8 @@ import TagList from "../components/items/TagList";
|
|||||||
import IngredientList from "../components/items/IngredientList";
|
import IngredientList from "../components/items/IngredientList";
|
||||||
import InstructionList from "../components/items/InstructionList";
|
import InstructionList from "../components/items/InstructionList";
|
||||||
import Spinner from "../components/Spinner";
|
import Spinner from "../components/Spinner";
|
||||||
|
import { GetUser } from "../services/UserService";
|
||||||
|
import type { User } from "../types/user";
|
||||||
|
|
||||||
export default function RecipePage() {
|
export default function RecipePage() {
|
||||||
// Url params
|
// Url params
|
||||||
@ -20,6 +22,7 @@ export default function RecipePage() {
|
|||||||
|
|
||||||
// Page state
|
// Page state
|
||||||
const [recipe, setRecipe] = useState<Recipe | null>(null);
|
const [recipe, setRecipe] = useState<Recipe | null>(null);
|
||||||
|
const [author, setAuthor] = useState<User | null>(null);
|
||||||
const [error, setError] = useState<string>("");
|
const [error, setError] = useState<string>("");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -34,6 +37,20 @@ export default function RecipePage() {
|
|||||||
void fetch();
|
void fetch();
|
||||||
}, [id]);
|
}, [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
|
// BUG: Prob remove
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (error)
|
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} />
|
<img className="bg-gray-100 w-full h-96 mx-auto mb-8" src={RecipePlaceholder} />
|
||||||
<div className="px-4 py-8 md:px-8">
|
<div className="px-4 py-8 md:px-8">
|
||||||
<h1 className="text-3xl md:text-4xl font-bold text-gray-800">{recipe.Title}</h1>
|
<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>
|
<p className="text-sm mb-2 text-gray-700">Category: {recipe.Category}</p>
|
||||||
</div>
|
</div>
|
||||||
<RecipeMetaData recipe={recipe} />
|
<RecipeMetaData recipe={recipe} />
|
||||||
|
|||||||
@ -1,10 +1,23 @@
|
|||||||
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 { 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 { Recipe } from "../types/recipe";
|
||||||
import type { Engagement } from "../types/engagement";
|
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> {
|
export async function GetAuthenticatedUser(): Promise<User | ApiError> {
|
||||||
const response = await axios.get<GetAuthenticateUserResponse>("http://localhost:3000/v2/api/user");
|
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 { Recipe } from "../recipe";
|
||||||
import type { User } from "../user";
|
import type { User } from "../user";
|
||||||
|
|
||||||
|
export interface GetUserResponse {
|
||||||
|
status: number;
|
||||||
|
message: string;
|
||||||
|
user?: User;
|
||||||
|
}
|
||||||
|
|
||||||
export interface GetAuthenticateUserResponse {
|
export interface GetAuthenticateUserResponse {
|
||||||
status: number;
|
status: number;
|
||||||
message: string;
|
message: string;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user