add blog
This commit is contained in:
parent
0b7c30d9c9
commit
445a233536
129
components/blogposts/001/index.jsx
Normal file
129
components/blogposts/001/index.jsx
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Imports
|
||||||
|
* ==============================================================================
|
||||||
|
*/
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Main Component { Functional }
|
||||||
|
* ==============================================================================
|
||||||
|
* @param {Object} props - Server props
|
||||||
|
*/
|
||||||
|
export default function Homepage(props) {
|
||||||
|
// ## Get Contexts
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Javascript Variables
|
||||||
|
/** ********************* Head Items */
|
||||||
|
let head = (
|
||||||
|
<React.Fragment>
|
||||||
|
<title>Showmerebates | Home</title>
|
||||||
|
<meta name="description" content="Find great property rebates" />
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## React Hooks { useState, useEffect, useRef, etc ... }
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Function Return
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<GeneralLayout head={ head } user={ props.user }>
|
||||||
|
<main>
|
||||||
|
<Hero />
|
||||||
|
<HowItWorks />
|
||||||
|
<FeaturedProperties data={ props.data } user={ props.user } />
|
||||||
|
<AboutUsSection />
|
||||||
|
{ !props.user && <LoginPromptPopup user={ props.user } /> }
|
||||||
|
</main>
|
||||||
|
</GeneralLayout>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Server Side Props or Static Props
|
||||||
|
* ==============================================================================
|
||||||
|
* @param {Object} req - http incoming request object
|
||||||
|
* @param {Object} res - http response object
|
||||||
|
* @param {Object} query - queries attached to the url
|
||||||
|
*/
|
||||||
|
export async function getServerSideProps({ req, res, query }) {
|
||||||
|
// ## Environment processes
|
||||||
|
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## User Authentication
|
||||||
|
const user = await userAuth(req, res);
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Page/Site Data Data Fetching
|
||||||
|
let properties = await dbHandler(`
|
||||||
|
SELECT
|
||||||
|
ListingKeyNumeric,City,RoomsTotal,BathroomsFull,BathroomsTotalInteger,BedroomsTotal,UnparsedAddress,BuildingAreaTotal,ListPrice,PostalCode
|
||||||
|
FROM
|
||||||
|
utahapidata
|
||||||
|
WHERE
|
||||||
|
PhotosCount > 0 AND ListPrice > 0 AND BedroomsTotal > 0 LIMIT 3
|
||||||
|
`);
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Server Props Return
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
user: user,
|
||||||
|
data: properties,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
}
|
73
components/blogposts/SingleBlogPostPreset.jsx
Normal file
73
components/blogposts/SingleBlogPostPreset.jsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Imports
|
||||||
|
* ==============================================================================
|
||||||
|
*/
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Main Component { Functional }
|
||||||
|
* ==============================================================================
|
||||||
|
* @param {Object} props - Server props
|
||||||
|
*/
|
||||||
|
export default function SingleBlogPostPreset(props) {
|
||||||
|
// ## Get Contexts
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Javascript Variables
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## React Hooks { useState, useEffect, useRef, etc ... }
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Function Return
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<GeneralLayout head={ head } user={ props.user }>
|
||||||
|
<main>
|
||||||
|
<Hero />
|
||||||
|
<HowItWorks />
|
||||||
|
<FeaturedProperties data={ props.data } user={ props.user } />
|
||||||
|
<AboutUsSection />
|
||||||
|
{ !props.user && <LoginPromptPopup user={ props.user } /> }
|
||||||
|
</main>
|
||||||
|
</GeneralLayout>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
6
components/blogposts/index.json
Normal file
6
components/blogposts/index.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"title": "",
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
]
|
79
jsonData/blogposts.json
Normal file
79
jsonData/blogposts.json
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"title": "Choosing your stack",
|
||||||
|
"slug": "choosing-your-tech-stack",
|
||||||
|
"description": "So many technologies, so little time to vet all",
|
||||||
|
"date": "Fri Jun 10 2022 06:34:08 GMT+0100 (West Africa Standard Time)",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"tag": "p",
|
||||||
|
"content": "The tech pool is an ever growing trojan horse. JavaScript libraries alone are getting out of hand: we seem to be getting a new one every 6 months. Hell even I have a javascript library of my own. Trying to pick from this pool can easily turn into mission impossible: understandably so: there's just too many of them"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "p",
|
||||||
|
"content": "The thing is, each of these libraries and frameworks end up doing essentially the same thing in thier respective categories: react creates reuseable javascript components: same with vue, same with angular, svelte. And for the most part, you won't be using every single feature provided by these libraries: just the ones that suit your project."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "p",
|
||||||
|
"content": "In truth, the tech stack you choose doesn't mean much: you can get 10 different options which achieve the same goal. Really, all that matters is the developer you pick: because a masterful developer can create great products using any stack of his/her choosing."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "p",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"tag": "span",
|
||||||
|
"content": "If you're just starting off, perhaps the best step is to evaluate the stacks and get a recommendation from an expert in the field: you may be surprised to find out you don't need as many technologies as you think: you may even be surprised that using a traditional framework like ruby on rails is actually a lot easier than wordpress. "
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "a",
|
||||||
|
"href": "/contact",
|
||||||
|
"class": "text-blue-300",
|
||||||
|
"content": "Reach out"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "span",
|
||||||
|
"content": " to find out more."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"title": "Find your perfect framework",
|
||||||
|
"slug": "find-your-perfect-framework",
|
||||||
|
"description": "How much can a web framework affect your project?",
|
||||||
|
"date": "Fri Jun 10 2022 06:34:08 GMT+0100 (West Africa Standard Time)",
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"tag": "p",
|
||||||
|
"content": "Web frameworks are a great way to get the best out of multiple technologies while keeping your development time short and reliability high. But just like it is with every aspect of web development, there's a dilemma of \"Which framework should I go with\"."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "p",
|
||||||
|
"content": "Different frameworks come with different structures and different selections of languages and packages. In truth, you don't necessarily need a framework: nearly all major programming languages can handle applications on thier own: but as you build more projects, you keep encountering more repetitions, and you end up abstracting those repetitions into reuseable components: you now have a framework of your own. Now this isn't bad at all: infact, this is the end goal of a truly performant app: frameworks often come with a lot of packages you may not need: which end up bugging down your application: if you can develop a framework of your own, you can eliminate this downside: but, you have to be prepared to spend a lot of time on your project: if you have the time, then go for it: else, go for a framework."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "p",
|
||||||
|
"content": "Haven said this, there are lots of frameworks you can choose from: depending on your time and budget: here are some great picks you should consider:"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "h2",
|
||||||
|
"content": "1. Next JS"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "img",
|
||||||
|
"src": "https://miro.medium.com/max/1400/1*htbUdWgFQ3a94PMEvBr_hQ.png",
|
||||||
|
"class": "w-full",
|
||||||
|
"style": {
|
||||||
|
"border": "1px solid #ffffff40"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tag": "p",
|
||||||
|
"content": "Next JS is slowly becoming the household name for web development frameworks: it features an immensely paowerful and efficient structure, based on React JS: which enables server side rendering of pages: as opposed to the traditional SPA(single page application) model React was created for. Next JS handles the heavilifting of routing, apis, frontend and backend components, module bundling, and linting, leaving you with a relatively easy platform to integrate your project. Next JS is growing very quick and in no time, it will become the most used framework for enterprise applications"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -5,19 +5,38 @@ const GeneralHeader = () => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
function pushRouter(e) {
|
function pushRouter(e) {
|
||||||
|
e.preventDefault();
|
||||||
let url = e.target.dataset.href;
|
let url = e.target.dataset.href;
|
||||||
router.push(url);
|
router.push(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header>
|
<header>
|
||||||
<a className="logo-link-block" onClick={ () => { pushRouter("/") } }><h1>Tben.me</h1></a>
|
<a className="logo-link-block" onClick={ () => {
|
||||||
|
pushRouter("/")
|
||||||
|
} }><h1>Tben.me</h1></a>
|
||||||
<nav>
|
<nav>
|
||||||
<a data-href="/" onClick={ (e) => { pushRouter(e) } }>Home</a>
|
<a href='/' data-href="/" onClick={ (e) => {
|
||||||
<a data-href="/about" onClick={ (e) => { pushRouter(e) } }>About Me</a>
|
pushRouter(e)
|
||||||
<a data-href="/work" onClick={ (e) => { pushRouter(e) } }>My Work</a>
|
} }>Home</a>
|
||||||
|
|
||||||
|
<a href='/about' data-href="/about" onClick={ (e) => {
|
||||||
|
pushRouter(e)
|
||||||
|
} }>About Me</a>
|
||||||
|
|
||||||
|
<a href='/work' data-href="/work" onClick={ (e) => {
|
||||||
|
pushRouter(e)
|
||||||
|
} }>My Work</a>
|
||||||
|
|
||||||
|
<a href='/blog' data-href="/blog" onClick={ (e) => {
|
||||||
|
pushRouter(e)
|
||||||
|
} }>Blog</a>
|
||||||
|
|
||||||
<a data-href="#" href='/documents/Benjamin_Toby_CV-updated.pdf' target="_blank">My Resume</a>
|
<a data-href="#" href='/documents/Benjamin_Toby_CV-updated.pdf' target="_blank">My Resume</a>
|
||||||
<a data-href="/contact" onClick={ (e) => { pushRouter(e) } }>Contact Me</a>
|
|
||||||
|
<a href='/contact' data-href="/contact" onClick={ (e) => {
|
||||||
|
pushRouter(e)
|
||||||
|
} }>Contact Me</a>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
|
@ -63,8 +63,6 @@ const GeneralLayout = ({ children, pageName }) => {
|
|||||||
// document.getElementById("page-loader").style.opacity
|
// document.getElementById("page-loader").style.opacity
|
||||||
|
|
||||||
threeJsAnimations();
|
threeJsAnimations();
|
||||||
|
|
||||||
// setReadyState(true);
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
@ -82,6 +80,7 @@ const GeneralLayout = ({ children, pageName }) => {
|
|||||||
{ children }
|
{ children }
|
||||||
</main>
|
</main>
|
||||||
<GeneralFooter />
|
<GeneralFooter />
|
||||||
|
<div className='fixed top-0 left-0 -z-10' id='homepage-animation-wrapper'></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</SiteContext.Provider>
|
</SiteContext.Provider>
|
||||||
|
@ -6,6 +6,7 @@ export default function Document() {
|
|||||||
<Html>
|
<Html>
|
||||||
<Head>
|
<Head>
|
||||||
{/* <script src="https://unpkg.com/@barba/core"></script> */}
|
{/* <script src="https://unpkg.com/@barba/core"></script> */}
|
||||||
|
{/* <script src="/scripts/swup.js"></script> */}
|
||||||
<script src="/scripts/main.js" defer></script>
|
<script src="/scripts/main.js" defer></script>
|
||||||
</Head>
|
</Head>
|
||||||
<body className="bg-black">
|
<body className="bg-black">
|
||||||
|
@ -132,7 +132,6 @@ const about = () => {
|
|||||||
<a href='/documents/Benjamin_Toby_CV-updated.pdf' download={ true }>See my resume</a>
|
<a href='/documents/Benjamin_Toby_CV-updated.pdf' download={ true }>See my resume</a>
|
||||||
<a href='https://www.linkedin.com/in/benjamin-toby/' target="_blank">Linkedin</a>
|
<a href='https://www.linkedin.com/in/benjamin-toby/' target="_blank">Linkedin</a>
|
||||||
</div>
|
</div>
|
||||||
<div className='fixed top-0 left-0 -z-10' id='homepage-animation-wrapper'></div>
|
|
||||||
</GeneralLayout>
|
</GeneralLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
186
pages/blog/[single].jsx
Normal file
186
pages/blog/[single].jsx
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Imports
|
||||||
|
* ==============================================================================
|
||||||
|
*/
|
||||||
|
import React from "react";
|
||||||
|
import Head from "next/head";
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
import GeneralLayout from "../../layouts/general_layout/GeneralLayout";
|
||||||
|
import TextShuffler from "../../components/actions/TextShuffler";
|
||||||
|
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Main Component { Functional }
|
||||||
|
* ==============================================================================
|
||||||
|
* @param {Object} props - Server props
|
||||||
|
*/
|
||||||
|
export default function BlogIndex({ blogPost }) {
|
||||||
|
// ## Get Contexts
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Javascript Variables
|
||||||
|
let reactKey = 0;
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## React Hooks { useState, useEffect, useRef, etc ... }
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Function Return
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Head>
|
||||||
|
<title>{ blogPost.title } | Tben.me Blog</title>
|
||||||
|
<meta name="description" content={ blogPost.description } />
|
||||||
|
</Head>
|
||||||
|
<GeneralLayout>
|
||||||
|
<div className="flex flex-col items-start gap-2 mb-8 max-w-3xl">
|
||||||
|
<button
|
||||||
|
className="bg-transparent text-white/50 border-2 border-solid border-white/20"
|
||||||
|
onClick={ (e) => {
|
||||||
|
window.history.back()
|
||||||
|
} }
|
||||||
|
>Back</button>
|
||||||
|
<h1 className="m-0"><TextShuffler textInput={ blogPost.title } /></h1>
|
||||||
|
<span className="text-lg">
|
||||||
|
<TextShuffler textInput={ blogPost.description } />
|
||||||
|
</span>
|
||||||
|
<span className="text-base opacity-50">
|
||||||
|
<TextShuffler textInput={ blogPost.date.substring(0, 24) } />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col items-start max-w-3xl w-full gap-4 text-lg">
|
||||||
|
{ blogPost.body.map((element) => {
|
||||||
|
reactKey++;
|
||||||
|
|
||||||
|
if (element.tag.match(/img/i)) {
|
||||||
|
return <img
|
||||||
|
src={ element.src }
|
||||||
|
width={ element.width }
|
||||||
|
height={ element.height }
|
||||||
|
className={ element.class }
|
||||||
|
alt={ element.alt }
|
||||||
|
style={ element.style }
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
function construtElement(elementEntry) {
|
||||||
|
if (elementEntry.children) {
|
||||||
|
return (
|
||||||
|
<elementEntry.tag
|
||||||
|
key={ reactKey }
|
||||||
|
className={ elementEntry.class ? elementEntry.class : null }
|
||||||
|
href={ elementEntry.href }
|
||||||
|
style={ element.style }
|
||||||
|
>
|
||||||
|
{ elementEntry.children.map(child => construtElement(child)) }
|
||||||
|
</elementEntry.tag>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<elementEntry.tag
|
||||||
|
key={ reactKey }
|
||||||
|
className={ elementEntry.class ? elementEntry.class : null }
|
||||||
|
href={ elementEntry.href }
|
||||||
|
>
|
||||||
|
{ elementEntry.content }
|
||||||
|
</elementEntry.tag>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return construtElement(element);
|
||||||
|
}
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
</GeneralLayout>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Server Side Props or Static Props
|
||||||
|
* ==============================================================================
|
||||||
|
* @param {Object} req - http incoming request object
|
||||||
|
* @param {Object} res - http response object
|
||||||
|
* @param {Object} query - queries attached to the url
|
||||||
|
*/
|
||||||
|
export async function getServerSideProps({ req, res, query }) {
|
||||||
|
// ## Environment processes
|
||||||
|
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## User Authentication
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Page/Site Data Data Fetching
|
||||||
|
const blogPosts = JSON.parse(fs.readFileSync("./jsonData/blogposts.json", "utf8"));
|
||||||
|
|
||||||
|
let foundPost = blogPosts.filter(post => post.slug === query.single);
|
||||||
|
|
||||||
|
if (!foundPost || !foundPost[0]) return {
|
||||||
|
redirect: {
|
||||||
|
destination: "/blog",
|
||||||
|
permanent: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Server Props Return
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
blogPost: foundPost[0],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
}
|
131
pages/blog/index.jsx
Normal file
131
pages/blog/index.jsx
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Imports
|
||||||
|
* ==============================================================================
|
||||||
|
*/
|
||||||
|
import React from "react";
|
||||||
|
import Head from "next/head";
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
import GeneralLayout from "../../layouts/general_layout/GeneralLayout";
|
||||||
|
import TextShuffler from "../../components/actions/TextShuffler";
|
||||||
|
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Main Component { Functional }
|
||||||
|
* ==============================================================================
|
||||||
|
* @param {Object} props - Server props
|
||||||
|
*/
|
||||||
|
export default function BlogIndex(props) {
|
||||||
|
// ## Get Contexts
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Javascript Variables
|
||||||
|
// const blogPosts = require("../../jsonData/blogposts.json");
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## React Hooks { useState, useEffect, useRef, etc ... }
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Function Return
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<Head>
|
||||||
|
<title>Blog | Tben.me</title>
|
||||||
|
<meta name="description" content="Tech talks" />
|
||||||
|
</Head>
|
||||||
|
<GeneralLayout>
|
||||||
|
<h1 className="mb-8"><TextShuffler textInput="My Blog" /></h1>
|
||||||
|
<div className="flex flex-col items-start w-full gap-4">
|
||||||
|
{ props.blogPosts.map(post =>
|
||||||
|
<a
|
||||||
|
href={ `/blog/${post.slug}` }
|
||||||
|
className="flex flex-col items-start gap-2 w-full hover:bg-blue-600 border border-solid border-white/20 p-8 transition-all"
|
||||||
|
key={ post.id }
|
||||||
|
>
|
||||||
|
<h2 className="m-0"><TextShuffler textInput={ post.title } /></h2>
|
||||||
|
<span className="opacity-80"><TextShuffler textInput={ post.description } /></span>
|
||||||
|
<span className="text-sm opacity-50"><TextShuffler textInput={ post.date.substring(0, 24) } /></span>
|
||||||
|
</a>
|
||||||
|
) }
|
||||||
|
</div>
|
||||||
|
</GeneralLayout>
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
/** ****************************************************************************** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ==============================================================================
|
||||||
|
* Server Side Props or Static Props
|
||||||
|
* ==============================================================================
|
||||||
|
* @param {Object} req - http incoming request object
|
||||||
|
* @param {Object} res - http response object
|
||||||
|
* @param {Object} query - queries attached to the url
|
||||||
|
*/
|
||||||
|
export async function getServerSideProps({ req, res, query }) {
|
||||||
|
// ## Environment processes
|
||||||
|
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## User Authentication
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Page/Site Data Data Fetching
|
||||||
|
const blogPosts = fs.readFileSync("./jsonData/blogposts.json", "utf8");
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
|
||||||
|
// ## Server Props Return
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
blogPosts: JSON.parse(blogPosts).reverse(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
/** ********************************************** */
|
||||||
|
}
|
@ -29,7 +29,6 @@ const contact = () => {
|
|||||||
{ success === "Success" && <div className='message-response'>Success!!! <button onClick={ () => { window.location.reload() } }>Reload</button></div> }
|
{ success === "Success" && <div className='message-response'>Success!!! <button onClick={ () => { window.location.reload() } }>Reload</button></div> }
|
||||||
{ success === "Failed" && <div className='message-response failed'>Failed <button onClick={ () => { window.location.reload() } }>Reload</button></div> }
|
{ success === "Failed" && <div className='message-response failed'>Failed <button onClick={ () => { window.location.reload() } }>Reload</button></div> }
|
||||||
</form>
|
</form>
|
||||||
<div className='fixed top-0 left-0 -z-10' id='homepage-animation-wrapper'></div>
|
|
||||||
</GeneralLayout>
|
</GeneralLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ const index = () => {
|
|||||||
border: "2px solid white"
|
border: "2px solid white"
|
||||||
} }>Contact Me</a>
|
} }>Contact Me</a>
|
||||||
</div>
|
</div>
|
||||||
<div className='fixed top-0 left-0 -z-10' id='homepage-animation-wrapper'></div>
|
|
||||||
</GeneralLayout>
|
</GeneralLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ import Head from 'next/head'
|
|||||||
import TextShuffler from '../components/actions/TextShuffler'
|
import TextShuffler from '../components/actions/TextShuffler'
|
||||||
import GeneralLayout from '../layouts/general_layout/GeneralLayout'
|
import GeneralLayout from '../layouts/general_layout/GeneralLayout'
|
||||||
import PortfolioEntry from '../components/PortfolioEntry'
|
import PortfolioEntry from '../components/PortfolioEntry'
|
||||||
import threeJsAnimations from '../functions/frontend/threeJsAnimations'
|
|
||||||
|
|
||||||
const myWork = () => {
|
const myWork = () => {
|
||||||
const portfolioEntries = require("../components/portfolioEntries.json");
|
const portfolioEntries = require("../components/portfolioEntries.json");
|
||||||
@ -22,7 +21,6 @@ const myWork = () => {
|
|||||||
<div className='portfolio-entries-block mt-4'>
|
<div className='portfolio-entries-block mt-4'>
|
||||||
{ portfolioEntries.map(entry => <PortfolioEntry key={ entry.title } title={ entry.title } description={ entry.description } url={ entry.url } image={ entry.image } />) }
|
{ portfolioEntries.map(entry => <PortfolioEntry key={ entry.title } title={ entry.title } description={ entry.description } url={ entry.url } image={ entry.image } />) }
|
||||||
</div>
|
</div>
|
||||||
<div className='fixed top-0 left-0 -z-10' id='homepage-animation-wrapper'></div>
|
|
||||||
</GeneralLayout>
|
</GeneralLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
1
public/scripts/swup.js
Normal file
1
public/scripts/swup.js
Normal file
File diff suppressed because one or more lines are too long
@ -19,6 +19,7 @@ html {
|
|||||||
|
|
||||||
:root {
|
:root {
|
||||||
--main-color: #1668e4;
|
--main-color: #1668e4;
|
||||||
|
--main-color-lighter: #5698fc;
|
||||||
--dark-color: #201e1e;
|
--dark-color: #201e1e;
|
||||||
--sec-color-3: #688e26;
|
--sec-color-3: #688e26;
|
||||||
--sec-color-4: #adb2d3;
|
--sec-color-4: #adb2d3;
|
||||||
@ -83,6 +84,25 @@ h1 {
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
|
||||||
|
p a,
|
||||||
|
span a {
|
||||||
|
color: var(--main-color-lighter);
|
||||||
|
/* border-bottom: 1px solid var(--main-color-lighter); */
|
||||||
|
}
|
||||||
|
|
||||||
|
p a:hover,
|
||||||
|
span a:hover {
|
||||||
|
color: var(--main-color);
|
||||||
|
}
|
||||||
|
|
||||||
/* ################################################# -- Sliders */
|
/* ################################################# -- Sliders */
|
||||||
aside,
|
aside,
|
||||||
.side-nav-block {
|
.side-nav-block {
|
||||||
@ -330,6 +350,24 @@ textarea {
|
|||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
/* * */
|
||||||
|
|
||||||
|
/* .transition-fade {
|
||||||
|
transition: 0.4s;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.is-animating .transition-fade {
|
||||||
|
opacity: 0;
|
||||||
|
} */
|
||||||
|
|
||||||
/* ###############################################################################################
|
/* ###############################################################################################
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
##################################################################################################
|
##################################################################################################
|
||||||
|
@ -59,6 +59,10 @@
|
|||||||
z-index: -10
|
z-index: -10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.m-0 {
|
||||||
|
margin: 0px
|
||||||
|
}
|
||||||
|
|
||||||
.mt-4 {
|
.mt-4 {
|
||||||
margin-top: 1rem
|
margin-top: 1rem
|
||||||
}
|
}
|
||||||
@ -71,6 +75,26 @@
|
|||||||
margin-bottom: 0.25rem
|
margin-bottom: 0.25rem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mb-4 {
|
||||||
|
margin-bottom: 1rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-8 {
|
||||||
|
margin-bottom: 2rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-0 {
|
||||||
|
margin-bottom: 0px
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-3 {
|
||||||
|
margin-bottom: 0.75rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-2 {
|
||||||
|
margin-bottom: 0.5rem
|
||||||
|
}
|
||||||
|
|
||||||
.flex {
|
.flex {
|
||||||
display: flex
|
display: flex
|
||||||
}
|
}
|
||||||
@ -79,37 +103,86 @@
|
|||||||
height: 1.5rem
|
height: 1.5rem
|
||||||
}
|
}
|
||||||
|
|
||||||
.h-screen {
|
|
||||||
height: 100vh
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-full {
|
.w-full {
|
||||||
width: 100%
|
width: 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
.w-screen {
|
.max-w-xl {
|
||||||
width: 100vw
|
max-width: 36rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-2xl {
|
||||||
|
max-width: 42rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-3xl {
|
||||||
|
max-width: 48rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-w-4xl {
|
||||||
|
max-width: 56rem
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex-col {
|
.flex-col {
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
}
|
}
|
||||||
|
|
||||||
.items-center {
|
.items-start {
|
||||||
align-items: center
|
align-items: flex-start
|
||||||
}
|
}
|
||||||
|
|
||||||
.justify-center {
|
.gap-2 {
|
||||||
justify-content: center
|
gap: 0.5rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.gap-4 {
|
||||||
|
gap: 1rem
|
||||||
}
|
}
|
||||||
|
|
||||||
.border {
|
.border {
|
||||||
border-width: 1px
|
border-width: 1px
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-black {
|
.border-2 {
|
||||||
|
border-width: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-solid {
|
||||||
|
border-style: solid
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-blue-500 {
|
||||||
|
--tw-border-opacity: 1;
|
||||||
|
border-color: rgb(59 130 246 / var(--tw-border-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-white\/40 {
|
||||||
|
border-color: rgb(255 255 255 / 0.4)
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-white\/20 {
|
||||||
|
border-color: rgb(255 255 255 / 0.2)
|
||||||
|
}
|
||||||
|
|
||||||
|
.border-white\/50 {
|
||||||
|
border-color: rgb(255 255 255 / 0.5)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-blue-600 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(0 0 0 / var(--tw-bg-opacity))
|
background-color: rgb(37 99 235 / var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-transparent {
|
||||||
|
background-color: transparent
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-4 {
|
||||||
|
padding: 1rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-8 {
|
||||||
|
padding: 2rem
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-xl {
|
.text-xl {
|
||||||
@ -122,10 +195,29 @@
|
|||||||
line-height: 1.25rem
|
line-height: 1.25rem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-lg {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
line-height: 1.75rem
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-base {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5rem
|
||||||
|
}
|
||||||
|
|
||||||
.font-bold {
|
.font-bold {
|
||||||
font-weight: 700
|
font-weight: 700
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-white {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(255 255 255 / var(--tw-text-opacity))
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-white\/50 {
|
||||||
|
color: rgb(255 255 255 / 0.5)
|
||||||
|
}
|
||||||
|
|
||||||
.opacity-50 {
|
.opacity-50 {
|
||||||
opacity: 0.5
|
opacity: 0.5
|
||||||
}
|
}
|
||||||
@ -133,3 +225,46 @@
|
|||||||
.opacity-40 {
|
.opacity-40 {
|
||||||
opacity: 0.4
|
opacity: 0.4
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.opacity-90 {
|
||||||
|
opacity: 0.9
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity-60 {
|
||||||
|
opacity: 0.6
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity-20 {
|
||||||
|
opacity: 0.2
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity-30 {
|
||||||
|
opacity: 0.3
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity-70 {
|
||||||
|
opacity: 0.7
|
||||||
|
}
|
||||||
|
|
||||||
|
.opacity-80 {
|
||||||
|
opacity: 0.8
|
||||||
|
}
|
||||||
|
|
||||||
|
.outline {
|
||||||
|
outline-style: solid
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter {
|
||||||
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
|
||||||
|
}
|
||||||
|
|
||||||
|
.transition-all {
|
||||||
|
transition-property: all;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-duration: 150ms
|
||||||
|
}
|
||||||
|
|
||||||
|
.hover\:bg-blue-600:hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(37 99 235 / var(--tw-bg-opacity))
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user