(feat): layout refactoring

This commit is contained in:
Maksym Sadovnychyy 2022-05-20 22:31:34 +02:00
parent 2f65cd44b5
commit 7e4da741ec
6 changed files with 229 additions and 139 deletions

View File

@ -1,5 +1,5 @@
import React, { FC, useEffect } from 'react'
import { Route, Routes } from 'react-router'
import { Route, Routes, useLocation } from 'react-router'
//Redux
import { useSelector, useDispatch } from 'react-redux'
@ -36,6 +36,7 @@ const NestedRoutes = (routes: IRoute[], tag: string | undefined = undefined) =>
const App: FC = () => {
const { pathname } = useLocation()
const dispatch = useDispatch()
const { routes, adminRoutes, serviceRoutes } = useSelector((state: IReduxState) => state.settings)
@ -43,6 +44,13 @@ const App: FC = () => {
dispatch(settingsActionCreators.requestSettings())
}, [])
useEffect(() => {
window.scrollTo({
top: 0,
behavior: 'smooth',
})
}, [pathname])
return <>
<Routes>
{ NestedRoutes(routes, 'PublicLayout') }

View File

@ -6,10 +6,9 @@ import { IReduxState } from '../../../interfaces'
const Footer = () => {
let { siteName } = useSelector((state: IReduxState) => state.settings)
return <footer className="py-5 bg-dark">
return <footer className="py-3 bg-dark">
<Container fluid><p className="m-0 text-center text-white">Copyright &copy; {siteName} {(new Date).getFullYear()}</p></Container>
</footer>
}
export {

View File

@ -4,13 +4,13 @@ import { NavMenu } from './NavMenu'
import { Footer } from './Footer'
import { ILayout } from '../interfaces'
import s from './scss/style.module.scss'
import style from './scss/style.module.scss'
const PublicLayout: FC<ILayout> = ({ children = null }) => {
return <>
<NavMenu />
<div className={s.wrapper}>
<div className={s.content}>
<div className={style.wrapper}>
<div className={style.content}>
{children}
</div>
</div>

View File

@ -5,10 +5,16 @@ import { Card, CardBody, CardHeader, CardImg, Col, Container, Row } from 'reacts
const BlogCatalog = () => {
const items = [
{
id: "1"
slug: "1"
},
{
id: "2"
slug: "2"
},
{
slug: "2"
},
{
slugd: "2"
}
]
@ -41,24 +47,9 @@ const BlogCatalog = () => {
<Row>
{items.map((item, index) => <Col key={index} lg={6}>
<Card mb={4}>
<Link to={`blog/item/${item.id}`}>
<CardImg top src="https://dummyimage.com/850x350/dee2e6/6c757d.jpg" alt="..." />
</Link>
<CardBody>
<div className="small text-muted">January 1, 2022</div>
<h2 className="card-title h4">Post Title</h2>
<p className="card-text">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Reiciendis aliquid atque, nulla.</p>
<a className="btn btn-primary" href="#!">Read more </a>
</CardBody>
</Card>
<Card className="mb-4">
<Link to={`blog/item/${item.id}`}>
<Link to={`${item.slug}`}>
<CardImg top src="https://dummyimage.com/850x350/dee2e6/6c757d.jpg" alt="..." />
</Link>

View File

@ -0,0 +1,5 @@
import React from 'react'
const SideWidgets = () => {
return null
}

View File

@ -1,10 +1,202 @@
import * as React from 'react'
import React, { FC } from 'react'
import { Link } from 'react-router-dom'
import { Card, CardBody, CardFooter, CardImg, Col, Container, Row } from 'reactstrap'
import { FeatherIcon } from '../../components/FeatherIcons'
import style from './scss/style.module.scss'
interface IImage {
src: string,
alt: string
}
interface IBlogAuthor {
name: string,
image: IImage
}
interface IBlogItem {
image: IImage,
badge: string,
title: string,
text: string,
author: IBlogAuthor,
date: string,
readTime: string
}
interface ITitleSection {
title: string,
text: string
}
const TitleSection : FC<ITitleSection> = (props) => {
const { title, text } = props
return <header className="py-5 bg-dark">
<Container fluid className="px-5">
<Row className="gx-5 align-items-center justify-content-center">
<Col className="lg-8 xl-7 xxl-6">
<div className="my-5 text-center text-xl-start">
<h1 className="display-5 fw-bolder text-white mb-2">{title}</h1>
<span className="lead fw-normal text-white-50 mb-4" dangerouslySetInnerHTML={{ __html: text }}>
</span>
<div className="d-grid gap-3 d-sm-flex justify-content-sm-center justify-content-xl-start">
<a className="btn btn-primary btn-lg px-4 me-sm-3" href="#features">Get Started</a>
<a className="btn btn-outline-light btn-lg px-4" href="#!">Learn More</a>
</div>
</div>
</Col>
<div className="col-xl-5 col-xxl-6 d-none d-xl-block text-center"><img className="img-fluid rounded-3 my-5" src="https://dummyimage.com/600x400/343a40/6c757d" alt="..." /></div>
</Row>
</Container>
</header>
}
interface IFeaturesSectionItem {
icon: string,
title: string,
text: string
}
interface IFeaturesSection {
title: string,
items: IFeaturesSectionItem [],
}
const FeaturesSection: FC<IFeaturesSection> = (props) => {
const { title, items } = props
return <section className="py-5" id="features">
<Container fluid className="px-5 my-5">
<Row className="gx-5">
<Col className="lg-4 mb-5 mb-lg-0">
<h2 className="fw-bolder mb-0">{title}</h2>
</Col>
<Col className="lg-8">
<Row className="gx-5 cols-1 cols-md-2">
{items.map((item, index) => <Col key={index} className="mb-5 h-100">
<div className={`${style.feature} bg-primary bg-gradient text-white rounded-3 mb-3`}>
<FeatherIcon icon={item.icon} />
</div>
<h2 className="h5">{item.title}</h2>
<p className="mb-0" dangerouslySetInnerHTML={{ __html: item.text }}></p>
</Col>)}
</Row>
</Col>
</Row>
</Container>
</section>
}
interface ITestimonialsSection {
text: string,
image: IImage
}
const TestimonialsSection: FC<ITestimonialsSection> = (props) => {
const { text, image } = props
return <section className="py-5 bg-light">
<Container fluid className="px-5 my-5">
<Row className="gx-5 justify-content-center">
<Col className="lg-10 xl-7">
<div className="text-center">
<div className="fs-4 mb-4 fst-italic" dangerouslySetInnerHTML={{ __html: text }}></div>
<div className="d-flex align-items-center justify-content-center">
<img className="rounded-circle me-3" {...image} />
<div className="fw-bold">Tom Ato<span className="fw-bold text-primary mx-1">/</span>CEO, Pomodoro
</div>
</div>
</div>
</Col>
</Row>
</Container>
</section>
}
interface IFromOurBlogSection {
title: string,
text: string,
items: IBlogItem []
}
const FromOurBlogSection: FC<IFromOurBlogSection> = (props) => {
const { title, text, items } = props
return <section className="py-5">
<Container fluid className="px-5 my-5">
<Row className="gx-5 justify-content-center">
<Col className="lg-8 xl-6">
<div className="text-center">
<h2 className="fw-bolder">{title}</h2>
<p className="lead fw-normal text-muted mb-5" dangerouslySetInnerHTML={{ __html: text }}></p>
</div>
</Col>
</Row>
<Row className="gx-5">
{items.map((item, index) => <Col key={index} className="lg-4 mb-5">
<Card className="h-100 shadow border-0">
<CardImg top {...item.image} />
<CardBody className="p-4">
<div className="badge bg-primary bg-gradient rounded-pill mb-2">{item.badge}</div>
<Link className="text-decoration-none link-dark stretched-link" to="#!">
<h5 className="card-title mb-3">{item.title}</h5>
</Link>
<p className="card-text mb-0" dangerouslySetInnerHTML={{ __html: text }}></p>
</CardBody>
<CardFooter className="p-4 pt-0 bg-transparent border-top-0">
<div className="d-flex align-items-end justify-content-between">
<div className="d-flex align-items-center">
<img className="rounded-circle me-3" {...item.author.image} />
<div className="small">
<div className="fw-bold">{item.author.name}</div>
<div className="text-muted">{item.date} &middot; {item.readTime}</div>
</div>
</div>
</div>
</CardFooter>
</Card>
</Col>)}
</Row>
</Container>
</section>
}
interface ICallToActionSection {
title: string,
text: string,
privacyDisclaimer: string
}
const CallToActionSection: FC<ICallToActionSection> = (props) => {
const { title, text, privacyDisclaimer } = props
return <section className="py-5">
<Container fluid className="px-5 my-5">
<aside className="bg-primary bg-gradient rounded-3 p-4 p-sm-5 mt-5">
<div className="d-flex align-items-center justify-content-between flex-column flex-xl-row text-center text-xl-start">
<div className="mb-4 mb-xl-0">
<div className="fs-3 fw-bold text-white">{title}</div>
<div className="text-white-50">{text}</div>
</div>
<div className="ms-xl-4">
<div className="input-group mb-2">
<input className="form-control" type="text" placeholder="Email address..." aria-label="Email address..." aria-describedby="button-newsletter" />
<button className="btn btn-outline-light" id="button-newsletter" type="button">Sign up</button>
</div>
<div className="small text-white-50">{privacyDisclaimer}</div>
</div>
</div>
</aside>
</Container>
</section>
}
const Home = () => {
const titleSection = {
title: "Hello, world!",
@ -40,7 +232,7 @@ const Home = () => {
}
const testimonialsSection = {
text: "The <code>ClientApp</code> subdirectory is a standard React application based on the <code>create-react-app</code> template. If you open a command prompt in that directory, you can run <code>npm</code> commands such as <code>npm test</code> or <code>npm install</code>.",
text: "The <code>ClientApp</code> subdirectory is a standard React application based on the <code>create-react-app</code> template. If you open a command prompt in that directory, you can run <code>yarn</code> commands such as <code>yarn test</code> or <code>yarn install</code>.",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
alt: "..."
@ -109,122 +301,17 @@ const Home = () => {
}
const callToActionSection = {
title: "New products, delivered to you.",
text: "Sign up for our newsletter for the latest updates.",
privacyDisclaimer: "We care about privacy, and will never share your data."
}
return <>
<header className="py-5 bg-dark">
<Container fluid className="px-5">
<Row className="gx-5 align-items-center justify-content-center">
<Col className="lg-8 xl-7 xxl-6">
<div className="my-5 text-center text-xl-start">
<h1 className="display-5 fw-bolder text-white mb-2">{titleSection.title}</h1>
<span className="lead fw-normal text-white-50 mb-4" dangerouslySetInnerHTML={{ __html: titleSection.text }}>
</span>
<div className="d-grid gap-3 d-sm-flex justify-content-sm-center justify-content-xl-start">
<a className="btn btn-primary btn-lg px-4 me-sm-3" href="#features">Get Started</a>
<a className="btn btn-outline-light btn-lg px-4" href="#!">Learn More</a>
</div>
</div>
</Col>
<div className="col-xl-5 col-xxl-6 d-none d-xl-block text-center"><img className="img-fluid rounded-3 my-5" src="https://dummyimage.com/600x400/343a40/6c757d" alt="..." /></div>
</Row>
</Container>
</header>
<section className="py-5" id="features">
<Container fluid className="px-5 my-5">
<Row className="gx-5">
<Col className="lg-4 mb-5 mb-lg-0">
<h2 className="fw-bolder mb-0">{featuresSecton.title}</h2>
</Col>
<Col className="lg-8">
<Row className="gx-5 cols-1 cols-md-2">
{featuresSecton.items.map((item, index) => <Col key={index} className="mb-5 h-100">
<div className={`${style.feature} bg-primary bg-gradient text-white rounded-3 mb-3`}>
<FeatherIcon icon={item.icon} />
</div>
<h2 className="h5">{item.title}</h2>
<p className="mb-0" dangerouslySetInnerHTML={{ __html: item.text }}></p>
</Col>)}
</Row>
</Col>
</Row>
</Container>
</section>
<div className="py-5 bg-light">
<Container fluid className="px-5 my-5">
<Row className="gx-5 justify-content-center">
<Col className="lg-10 xl-7">
<div className="text-center">
<div className="fs-4 mb-4 fst-italic" dangerouslySetInnerHTML={{ __html: testimonialsSection.text }}></div>
<div className="d-flex align-items-center justify-content-center">
<img className="rounded-circle me-3" {...testimonialsSection.image} />
<div className="fw-bold">Tom Ato<span className="fw-bold text-primary mx-1">/</span>CEO, Pomodoro
</div>
</div>
</div>
</Col>
</Row>
</Container>
</div>
<section className="py-5">
<Container fluid className="px-5 my-5">
<Row className="gx-5 justify-content-center">
<Col className="lg-8 xl-6">
<div className="text-center">
<h2 className="fw-bolder">{fromOurBlogSection.title}</h2>
<p className="lead fw-normal text-muted mb-5" dangerouslySetInnerHTML={{ __html: fromOurBlogSection.text }}></p>
</div>
</Col>
</Row>
<Row className="gx-5">
{fromOurBlogSection.items.map((item, index) => <Col key={index} className="lg-4 mb-5">
<Card className="h-100 shadow border-0">
<CardImg top {...item.image} />
<CardBody className="p-4">
<div className="badge bg-primary bg-gradient rounded-pill mb-2">{item.badge}</div>
<Link className="text-decoration-none link-dark stretched-link" to="#!">
<h5 className="card-title mb-3">{item.title}</h5>
</Link>
<p className="card-text mb-0" dangerouslySetInnerHTML={{ __html: item.text }}></p>
</CardBody>
<CardFooter className="p-4 pt-0 bg-transparent border-top-0">
<div className="d-flex align-items-end justify-content-between">
<div className="d-flex align-items-center">
<img className="rounded-circle me-3" {...item.author.image} />
<div className="small">
<div className="fw-bold">{item.author.name}</div>
<div className="text-muted">{item.date} &middot; {item.readTime}</div>
</div>
</div>
</div>
</CardFooter>
</Card>
</Col>)}
</Row>
<aside className="bg-primary bg-gradient rounded-3 p-4 p-sm-5 mt-5">
<div className="d-flex align-items-center justify-content-between flex-column flex-xl-row text-center text-xl-start">
<div className="mb-4 mb-xl-0">
<div className="fs-3 fw-bold text-white">New products, delivered to you.</div>
<div className="text-white-50">Sign up for our newsletter for the latest updates.</div>
</div>
<div className="ms-xl-4">
<div className="input-group mb-2">
<input className="form-control" type="text" placeholder="Email address..." aria-label="Email address..." aria-describedby="button-newsletter" />
<button className="btn btn-outline-light" id="button-newsletter" type="button">Sign up</button>
</div>
<div className="small text-white-50">We care about privacy, and will never share your data.</div>
</div>
</div>
</aside>
</Container>
</section>
<TitleSection {...titleSection}/>
<FeaturesSection {...featuresSecton} />
<TestimonialsSection {...testimonialsSection} />
<FromOurBlogSection {...fromOurBlogSection} />
<CallToActionSection {...callToActionSection} />
</>
}