Refactoring of components and styling of full recipe page.

This commit is contained in:
Jesse Brault 2024-08-01 15:38:20 -05:00
parent a983d49f22
commit a3443ce274
12 changed files with 123 additions and 47 deletions

View File

@ -40,7 +40,8 @@ const getRecipe = async ({
ownerUsername, ownerUsername,
starCount, starCount,
viewerCount, viewerCount,
mainImage: rawMainImage mainImage: rawMainImage,
isPublic
} = (await response.json()) as RawFullRecipeView } = (await response.json()) as RawFullRecipeView
return { return {
id, id,
@ -53,7 +54,8 @@ const getRecipe = async ({
ownerUsername, ownerUsername,
starCount, starCount,
viewerCount, viewerCount,
mainImage: toImageView(rawMainImage) mainImage: toImageView(rawMainImage),
isPublic
} }
} else if (response.status === 404) { } else if (response.status === 404) {
throw notFound() throw notFound()

View File

@ -12,6 +12,7 @@ export interface RawFullRecipeView {
starCount: number starCount: number
viewerCount: number viewerCount: number
mainImage: RawImageView mainImage: RawImageView
isPublic: boolean
} }
interface FullRecipeView { interface FullRecipeView {
@ -26,6 +27,7 @@ interface FullRecipeView {
starCount: number starCount: number
viewerCount: number viewerCount: number
mainImage: ImageView mainImage: ImageView
isPublic: boolean
} }
export default FullRecipeView export default FullRecipeView

View File

@ -1,6 +1,8 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import classes from './recipe-card.module.css'
import { Link } from '@tanstack/react-router' import { Link } from '@tanstack/react-router'
import RecipeVisibilityIcon from '../recipe-visibility-icon/RecipeVisibilityIcon'
import StarCount from '../star-count/StarCount'
import UserIconAndName from '../user-icon-and-name/UserIconAndName'
import classes from './recipe-card.module.css'
export interface RecipeCardProps { export interface RecipeCardProps {
title: string title: string
@ -49,28 +51,11 @@ const RecipeCard = ({
> >
<h1 className={classes.title}>{title}</h1> <h1 className={classes.title}>{title}</h1>
</Link> </Link>
<span className={classes.starInfo}> <StarCount count={starCount} />
<FontAwesomeIcon
icon="star"
className={classes.star}
size="sm"
/>
{starCount}
</span>
</div> </div>
<div className={classes.infoRow}> <div className={classes.infoRow}>
<span className={classes.userInfo}> <UserIconAndName username={ownerUsername} />
<FontAwesomeIcon <RecipeVisibilityIcon isPublic={isPublic} />
icon="user"
className={classes.userIcon}
/>
{ownerUsername}
</span>
{isPublic ? (
<FontAwesomeIcon icon="globe" size="sm" />
) : (
<FontAwesomeIcon icon="lock" size="sm" />
)}
</div> </div>
</div> </div>
</article> </article>

View File

@ -23,22 +23,3 @@
margin-block: 0; margin-block: 0;
font-size: 18px; font-size: 18px;
} }
.star-info {
display: flex;
column-gap: 5px;
align-items: center;
}
.star {
color: var(--primary-yellow);
}
.user-info {
display: flex;
column-gap: 5px;
}
.user-icon {
color: var(--primary-red);
}

View File

@ -0,0 +1,23 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import classes from './recipe-visibility-icon.module.css'
export interface RecipeVisibilityIconProps {
isPublic: boolean
}
const RecipeVisibilityIcon = ({ isPublic }: RecipeVisibilityIconProps) =>
isPublic ? (
<FontAwesomeIcon
icon="globe"
className={classes.recipeVisibilityIcon}
size="sm"
/>
) : (
<FontAwesomeIcon
icon="lock"
className={classes.recipeVisibilityIcon}
size="sm"
/>
)
export default RecipeVisibilityIcon

View File

@ -0,0 +1,3 @@
.recipe-visibility-icon {
color: var(--primary-red);
}

View File

@ -0,0 +1,15 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import classes from './star-count.module.css'
export interface StarCountProps {
count: number
}
const StarCount = ({ count }: StarCountProps) => (
<span className={classes.starInfo}>
<FontAwesomeIcon icon="star" className={classes.star} size="sm" />
{count}
</span>
)
export default StarCount

View File

@ -0,0 +1,9 @@
.star-info {
display: flex;
column-gap: 5px;
align-items: center;
}
.star {
color: var(--primary-yellow);
}

View File

@ -0,0 +1,15 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import classes from './user-icon-and-name.module.css'
export interface UserIconAndNameProps {
username: string
}
const UserIconAndName = ({ username }: UserIconAndNameProps) => (
<span className={classes.userInfo}>
<FontAwesomeIcon icon="user" className={classes.userIcon} />
{username}
</span>
)
export default UserIconAndName

View File

@ -0,0 +1,8 @@
.user-info {
display: flex;
column-gap: 5px;
}
.user-icon {
color: var(--primary-red);
}

View File

@ -1,4 +1,8 @@
import FullRecipeView from '../../api/types/FullRecipeView' import FullRecipeView from '../../api/types/FullRecipeView'
import RecipeVisibilityIcon from '../../components/recipe-visibility-icon/RecipeVisibilityIcon'
import StarCount from '../../components/star-count/StarCount'
import UserIconAndName from '../../components/user-icon-and-name/UserIconAndName'
import classes from './recipe.module.css'
export interface RecipeProps { export interface RecipeProps {
recipe: FullRecipeView recipe: FullRecipeView
@ -6,10 +10,20 @@ export interface RecipeProps {
const Recipe = ({ recipe }: RecipeProps) => { const Recipe = ({ recipe }: RecipeProps) => {
return ( return (
<article> <div className={classes.fullRecipeContainer}>
<article className={classes.fullRecipe}>
<img src={recipe.mainImage.url} className={classes.mainImage} />
<div className={classes.infoRow}>
<h1>{recipe.title}</h1> <h1>{recipe.title}</h1>
<StarCount count={recipe.starCount} />
</div>
<div className={classes.infoRow}>
<UserIconAndName username={recipe.ownerUsername} />
<RecipeVisibilityIcon isPublic={recipe.isPublic} />
</div>
<div dangerouslySetInnerHTML={{ __html: recipe.text }} /> <div dangerouslySetInnerHTML={{ __html: recipe.text }} />
</article> </article>
</div>
) )
} }

View File

@ -0,0 +1,19 @@
.full-recipe-container {
display: flex;
flex-direction: column;
align-items: center;
max-width: 100%;
}
.full-recipe {
max-width: 600px;
}
.full-recipe .main-image {
width: 100%;
}
.full-recipe .info-row {
display: flex;
justify-content: space-between;
}