(feat): layout refactoring
This commit is contained in:
parent
2f65cd44b5
commit
7e4da741ec
@ -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') }
|
||||
|
||||
@ -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 © {siteName} {(new Date).getFullYear()}</p></Container>
|
||||
</footer>
|
||||
|
||||
}
|
||||
|
||||
export {
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
|
||||
5
clientapp/src/pages/Blog/SideWidgets/index.tsx
Normal file
5
clientapp/src/pages/Blog/SideWidgets/index.tsx
Normal file
@ -0,0 +1,5 @@
|
||||
import React from 'react'
|
||||
|
||||
const SideWidgets = () => {
|
||||
return null
|
||||
}
|
||||
@ -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} · {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} · {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} />
|
||||
</>
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user