-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
613 additions
and
71 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 4 additions & 14 deletions
18
src/layouts/blog-tab-layout/components/blog-tab/BlogTab.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,20 @@ | ||
import { Link } from "react-router-dom"; | ||
|
||
import Box from "@mui/material/Box"; | ||
|
||
import { PostCategory } from "@/api/generated"; | ||
import useSearchParamsActions from "@/hooks/use-search-params-actions/useSearchParamsActions"; | ||
import { BlogTabButton } from "@/layouts/blog-tab-layout/components/blog-tab/BlogTab.styles"; | ||
|
||
type BlogTabProps = { | ||
categoryLabel: PostCategory["name"]; | ||
categorySlug?: PostCategory["slug"]; | ||
}; | ||
|
||
export default function BlogTab({ categoryLabel, categorySlug }: BlogTabProps) { | ||
const { setSearchParam, deleteSearchParam } = useSearchParamsActions(); | ||
|
||
const handleClick = () => { | ||
if (categorySlug) { | ||
setSearchParam("category", categorySlug); | ||
} else { | ||
deleteSearchParam("category"); | ||
} | ||
}; | ||
const to = categorySlug ? `/posts?category=${categorySlug}` : "/posts"; | ||
|
||
return ( | ||
<Box component="li"> | ||
<BlogTabButton disableRipple disableTouchRipple onClick={handleClick}> | ||
{categoryLabel} | ||
</BlogTabButton> | ||
<Link to={to}>{categoryLabel}</Link> | ||
</Box> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { styled } from "@mui/material"; | ||
import Container from "@mui/material/Container"; | ||
|
||
type ColoredWrapperProps = { | ||
backgroundColor: string; | ||
}; | ||
|
||
export const ColoredWrapper = styled("section", { | ||
shouldForwardProp: prop => prop !== "backgroundColor", | ||
})<ColoredWrapperProps>(props => ({ | ||
backgroundColor: props.backgroundColor, | ||
padding: "100px 0", | ||
})); | ||
|
||
type ContentWrapperProps = { | ||
backgroundColor: string; | ||
}; | ||
|
||
export const ContentWrapper = styled(Container, { | ||
shouldForwardProp: prop => prop !== "backgroundColor", | ||
})<ContentWrapperProps>(props => ({ | ||
backgroundColor: props.backgroundColor, | ||
maxWidth: "1058px !important", | ||
padding: "20px !important", | ||
})); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { PropsWithChildren } from "react"; | ||
|
||
import { | ||
ColoredWrapper, | ||
ContentWrapper, | ||
} from "@/layouts/page-wrapper/PageWrapper.styles"; | ||
import theme from "@/theme/theme"; | ||
|
||
type PageWrapperProps = PropsWithChildren<{ | ||
wrapperBackgroundColor?: string; | ||
containerBackgroundColor?: string; | ||
}>; | ||
|
||
export default function PageWrapper({ | ||
children, | ||
wrapperBackgroundColor = theme.palette.CreamyDawn.main, | ||
containerBackgroundColor = theme.palette.primary.main, | ||
}: PageWrapperProps) { | ||
return ( | ||
<ColoredWrapper backgroundColor={wrapperBackgroundColor}> | ||
<ContentWrapper backgroundColor={containerBackgroundColor}> | ||
{children} | ||
</ContentWrapper> | ||
</ColoredWrapper> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { styled } from "@mui/material"; | ||
import Box from "@mui/material/Box"; | ||
|
||
import theme from "@/theme/theme"; | ||
|
||
export const BlogHeader = styled(Box)({ | ||
marginBottom: "60px", | ||
}); | ||
|
||
export const PostWrapper = styled(Box)({ | ||
padding: "20px 100px 60px", | ||
border: `1px solid ${theme.palette.grey[300]}`, | ||
}); | ||
|
||
export const Title = styled("h2")({ | ||
...theme.typography.heading, | ||
fontSize: "28px", | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,73 @@ | ||
// import { useParams } from "react-router-dom"; | ||
import { Navigate } from "react-router-dom"; | ||
|
||
import Box from "@mui/material/Box"; | ||
import Typography from "@mui/material/Typography"; | ||
import DOMPurify from "dompurify"; | ||
|
||
import "@/containers/post-editor/PostEditor.content.css"; | ||
import BlogTabLayout from "@/layouts/blog-tab-layout/BlogTabLayout"; | ||
import PageWrapper from "@/layouts/page-wrapper/PageWrapper"; | ||
import { BlogHeader, PostWrapper, Title } from "@/pages/post/PostPage.styled"; | ||
import PostFooter from "@/pages/post/components/post-footer/PostFooter"; | ||
import PostHeader from "@/pages/post/components/post-header/PostHeader"; | ||
import theme from "@/theme/theme"; | ||
|
||
// import { PostPageParams } from "@/types/helpers"; | ||
|
||
// TODO: replace with real data from backend | ||
const title = "Why are Facials a Must for the Modern Woman"; | ||
|
||
const content = `<p>Create a blog post subtitle that summarizes your post in a few short, punchy sentences and entices your audience to continue reading.</p> | ||
<p><strong><img style="display: block; margin-left: auto; margin-right: auto;" src="https://static.wixstatic.com/media/84770f_170242c7269d4ba2ba8ad50591e1a1e8~mv2_d_4500_2992_s_4_2.jpg/v1/fill/w_925,h_615,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/84770f_170242c7269d4ba2ba8ad50591e1a1e8~mv2_d_4500_2992_s_4_2.jpg" width="668" height="444"></strong></p> | ||
<p>Welcome to your blog post. Use this space to connect with your readers and potential customers in a way that’s current and interesting. Think of it as an ongoing conversation where you can share updates about business, trends, news, and more.</p> | ||
<blockquote> | ||
<p><em>Do you have a design in mind for your blog? Whether you prefer a trendy postcard look or you’re going for a more editorial style blog - there’s a stunning layout for everyone.</em></p> | ||
</blockquote> | ||
<p>You’ll be posting loads of engaging content, so be sure to keep your blog organized with Categories that also allow visitors to explore more of what interests them.</p> | ||
<p><strong>Create Relevant Content</strong></p> | ||
<p> </p> | ||
<p>Writing a blog is a great way to position yourself as an authority in your field and captivate your readers’ attention. Do you want to improve your site’s SEO ranking? Consider topics that focus on relevant keywords and relate back to your website or business. You can also add hashtags (<a class="QzAlv iqUF1" href="https://social-blog.wix.com/search/posts%3Fquery=%23vacation" target="_top" rel="noopener" data-hook="WebLink"><u>#vacation</u></a><u> </u><a class="QzAlv iqUF1" href="https://social-blog.wix.com/search/posts%3Fquery=%23dream" target="_top" rel="noopener" data-hook="WebLink"><u>#dream</u></a><u> </u><a class="QzAlv iqUF1" href="https://social-blog.wix.com/search/posts%3Fquery=%23summer" target="_top" rel="noopener" data-hook="WebLink"><u>#summer</u></a>) throughout your posts to reach more people, and help visitors search for relevant content. Blogging gives your site a voice, so let your business’ personality shine through. Choose a great image to feature in your post or add a video for extra engagement. Are you ready to get started? Simply create a new post now.</p>`; | ||
// TODO: remove mock response and change type | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
const mockPostResponse: { data: { post: any } } = { | ||
data: { | ||
post: { | ||
author: { | ||
id: 1, | ||
username: "Admin", | ||
role: "ADMIN", | ||
}, | ||
createdAt: "2024-08-31T13:58:19.838Z", | ||
estimatedReadTime: 1, | ||
title: "Why are Facials a Must for the Modern Woman", | ||
content: | ||
'<p>Create a blog post subtitle that summarizes your post in a few short, punchy sentences and entices your audience to continue reading.</p>\n<p><strong><img style="display: block; margin-left: auto; margin-right: auto;" src="https://static.wixstatic.com/media/84770f_170242c7269d4ba2ba8ad50591e1a1e8~mv2_d_4500_2992_s_4_2.jpg/v1/fill/w_925,h_615,al_c,q_85,usm_0.66_1.00_0.01,enc_auto/84770f_170242c7269d4ba2ba8ad50591e1a1e8~mv2_d_4500_2992_s_4_2.jpg" width="668" height="444"></strong></p>\n<p>Welcome to your blog post. Use this space to connect with your readers and potential customers in a way that’s current and interesting. Think of it as an ongoing conversation where you can share updates about business, trends, news, and more.</p>\n<blockquote>\n<p><em>Do you have a design in mind for your blog? Whether you prefer a trendy postcard look or you’re going for a more editorial style blog - there’s a stunning layout for everyone.</em></p>\n</blockquote>\n<p>You’ll be posting loads of engaging content, so be sure to keep your blog organized with Categories that also allow visitors to explore more of what interests them.</p>\n<p><strong>Create Relevant Content</strong></p>\n<p> </p>\n<p>Writing a blog is a great way to position yourself as an authority in your field and captivate your readers’ attention. Do you want to improve your site’s SEO ranking? Consider topics that focus on relevant keywords and relate back to your website or business. You can also add hashtags (<a class="QzAlv iqUF1" href="https://social-blog.wix.com/search/posts%3Fquery=%23vacation" target="_top" rel="noopener" data-hook="WebLink"><u>#vacation</u></a><u> </u><a class="QzAlv iqUF1" href="https://social-blog.wix.com/search/posts%3Fquery=%23dream" target="_top" rel="noopener" data-hook="WebLink"><u>#dream</u></a><u> </u><a class="QzAlv iqUF1" href="https://social-blog.wix.com/search/posts%3Fquery=%23summer" target="_top" rel="noopener" data-hook="WebLink"><u>#summer</u></a>) throughout your posts to reach more people, and help visitors search for relevant content. Blogging gives your site a voice, so let your business’ personality shine through. Choose a great image to feature in your post or add a video for extra engagement. Are you ready to get started? Simply create a new post now.</p>', | ||
categories: [ | ||
{ | ||
name: "Daily Routine", | ||
slug: "daily-routine", | ||
}, | ||
{ | ||
name: "Herbs and Minerals", | ||
slug: "herbs-and-minerals", | ||
}, | ||
], | ||
viewsCount: 0, | ||
commentsCount: 0, | ||
isLiked: false, | ||
likesCount: 0, | ||
}, | ||
}, | ||
}; | ||
|
||
// TODO: complete with real UI | ||
export default function PostPage() { | ||
// TODO: use param to fetch post from backend | ||
// const params = useParams<PostPageParams>(); | ||
const { data } = mockPostResponse; | ||
|
||
const post = data?.post; | ||
|
||
if (!post) { | ||
// TODO: improve not found page | ||
return <Navigate to="/not-found" />; | ||
} | ||
|
||
const sanitizedContent = DOMPurify.sanitize(post.content); | ||
|
||
return ( | ||
<Box> | ||
<BlogTabLayout /> | ||
{/* TODO: change ui */} | ||
<Typography>{title}</Typography> | ||
{/* TODO: consider sanitizing */} | ||
<Box dangerouslySetInnerHTML={{ __html: content }} /> | ||
</Box> | ||
<PageWrapper wrapperBackgroundColor={theme.palette.PinkMarbleSky.main}> | ||
<BlogHeader> | ||
<BlogTabLayout /> | ||
</BlogHeader> | ||
<PostWrapper> | ||
<PostHeader post={post} /> | ||
<Title>{post.title}</Title> | ||
<Box dangerouslySetInnerHTML={{ __html: sanitizedContent }} /> | ||
<PostFooter post={post} /> | ||
</PostWrapper> | ||
</PageWrapper> | ||
); | ||
} |
16 changes: 16 additions & 0 deletions
16
src/pages/post/components/author-role-button/AuthorRoleButton.constants.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { ComponentType, SVGAttributes } from "react"; | ||
|
||
import CrownIcon from "@/assets/icons/crown.svg"; | ||
import UserIcon from "@/assets/icons/user-icon.svg"; | ||
|
||
import { USER_ROLES } from "@/constants"; | ||
import { UserRole } from "@/types/helpers"; | ||
|
||
export const postAuthorIconsByRole: Record< | ||
UserRole, | ||
ComponentType<SVGAttributes<SVGElement>> | ||
> = { | ||
[USER_ROLES.ADMIN]: CrownIcon, | ||
[USER_ROLES.USER]: UserIcon, | ||
[USER_ROLES.GUEST]: UserIcon, | ||
}; |
6 changes: 6 additions & 0 deletions
6
src/pages/post/components/author-role-button/AuthorRoleButton.styles.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { styled } from "@mui/material"; | ||
import IconButton from "@mui/material/IconButton"; | ||
|
||
export const IconButtonStyled = styled(IconButton)({ | ||
padding: "2px", | ||
}); |
49 changes: 49 additions & 0 deletions
49
src/pages/post/components/author-role-button/AuthorRoleButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import Tooltip, { tooltipClasses } from "@mui/material/Tooltip"; | ||
|
||
import { postAuthorIconsByRole } from "@/pages/post/components/author-role-button/AuthorRoleButton.constants"; | ||
import { IconButtonStyled } from "@/pages/post/components/author-role-button/AuthorRoleButton.styles"; | ||
import theme from "@/theme/theme"; | ||
import { UserRole } from "@/types/helpers"; | ||
|
||
type AuthorRoleButtonProps = { | ||
authorRole: UserRole; | ||
}; | ||
|
||
export default function AuthorRoleButton({ | ||
authorRole, | ||
}: AuthorRoleButtonProps) { | ||
const PostAuthorRoleIcon = postAuthorIconsByRole[authorRole]; | ||
|
||
return ( | ||
<Tooltip | ||
arrow | ||
placement="top" | ||
title={authorRole.toLowerCase()} | ||
slotProps={{ | ||
tooltip: { | ||
sx: { | ||
backgroundColor: theme.palette.secondary.main, | ||
}, | ||
}, | ||
arrow: { | ||
sx: { | ||
color: theme.palette.secondary.main, | ||
}, | ||
}, | ||
popper: { | ||
sx: { | ||
textTransform: "capitalize", | ||
[`&.${tooltipClasses.popper}[data-popper-placement*="top"] .${tooltipClasses.tooltip}`]: | ||
{ | ||
marginBottom: "0px", | ||
}, | ||
}, | ||
}, | ||
}} | ||
> | ||
<IconButtonStyled disableRipple> | ||
<PostAuthorRoleIcon width="20px" height="20px" /> | ||
</IconButtonStyled> | ||
</Tooltip> | ||
); | ||
} |
Oops, something went wrong.