This commit is contained in:
Benjamin Toby
2023-10-24 18:59:00 +01:00
parent d163438f7b
commit b9364a702c
68 changed files with 4701 additions and 4697 deletions
+15 -15
View File
@@ -1,15 +1,15 @@
import "../styles/main.css";
import "../styles/tw_main.css";
import { Fragment } from "react";
import type { AppProps } from "next/app";
function MyApp({ Component, pageProps }: AppProps) {
return (
<Fragment>
<Component {...pageProps} />
</Fragment>
);
}
export default MyApp;
import "../styles/main.css";
import "../styles/tw_main.css";
import { Fragment } from "react";
import type { AppProps } from "next/app";
function MyApp({ Component, pageProps }: AppProps) {
return (
<Fragment>
<Component {...pageProps} />
</Fragment>
);
}
export default MyApp;
+19 -19
View File
@@ -1,19 +1,19 @@
import React from "react";
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html>
<Head>
<script
src="/scripts/main.js"
defer
></script>
</Head>
<body className="w-full">
<Main />
<NextScript />
</body>
</Html>
);
}
import React from "react";
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html>
<Head>
<script
src="/scripts/main.js"
defer
></script>
</Head>
<body className="w-full">
<Main />
<NextScript />
</body>
</Html>
);
}
+49 -49
View File
@@ -1,49 +1,49 @@
/**
* Imports
*/
const fs = require("fs");
const sanitizeHtml = require("sanitize-html");
const nodemailer = require("nodemailer");
import sanitizeHtmlOptions from "../../functions/backend/sanitizeHtmlOptions";
import { NextApiRequest, NextApiResponse } from "next";
let transporter = nodemailer.createTransport({
host: process.env.TBENMAIL_HOST,
port: 587,
auth: {
user: process.env.TBENMAIL_EMAIL,
pass: process.env.TBENMAIL_EMAIL_PASSWORD,
},
});
/**
* API handler
*
*/
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "POST") {
let name = req.body.name;
let email = req.body.email;
let message = req.body.message;
const html = `<h1>Message from ${name} | ${email}</h1><h4>Name:</h4><p>${name}</p><h4>Email:</h4><p>${email}</p><h4>Message:</h4><p>${message}</p>`;
const sanitizedHtml = sanitizeHtml(html, sanitizeHtmlOptions);
try {
let info = await transporter.sendMail({
from: `"Tben.me" <${process.env.TBENMAIL_EMAIL}>`,
to: "benoti.san@gmail.com, benoti.sanchez@gmail.com",
subject: "Tben.me | Client Message",
text: "Hello from tben",
html: sanitizedHtml,
});
console.log("Message sent: %s", info.messageId);
res.json({ msg: "Success", info: info });
} catch (error) {
console.log(error);
res.json({ msg: "Failed" });
}
}
}
/**
* Imports
*/
const fs = require("fs");
const sanitizeHtml = require("sanitize-html");
const nodemailer = require("nodemailer");
import sanitizeHtmlOptions from "../../functions/backend/sanitizeHtmlOptions";
import { NextApiRequest, NextApiResponse } from "next";
let transporter = nodemailer.createTransport({
host: process.env.TBENMAIL_HOST,
port: 587,
auth: {
user: process.env.TBENMAIL_EMAIL,
pass: process.env.TBENMAIL_EMAIL_PASSWORD,
},
});
/**
* API handler
*
*/
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === "POST") {
let name = req.body.name;
let email = req.body.email;
let message = req.body.message;
const html = `<h1>Message from ${name} | ${email}</h1><h4>Name:</h4><p>${name}</p><h4>Email:</h4><p>${email}</p><h4>Message:</h4><p>${message}</p>`;
const sanitizedHtml = sanitizeHtml(html, sanitizeHtmlOptions);
try {
let info = await transporter.sendMail({
from: `"Tben.me" <${process.env.TBENMAIL_EMAIL}>`,
to: "benoti.san@gmail.com, benoti.sanchez@gmail.com",
subject: "Tben.me | Client Message",
text: "Hello from tben",
html: sanitizedHtml,
});
console.log("Message sent: %s", info.messageId);
res.json({ msg: "Success", info: info });
} catch (error) {
console.log(error);
res.json({ msg: "Failed" });
}
}
}
+45 -45
View File
@@ -1,45 +1,45 @@
import { NextApiHandler, NextApiRequest, NextApiResponse } from "next";
import Cors from "cors";
const cors = Cors({
methods: ["GET"],
origin: "*",
});
// Helper method to wait for a middleware to execute before continuing
// And to throw an error when an error happens in a middleware
function runMiddleware(req: NextApiRequest, res: NextApiResponse, fn: Function) {
return new Promise((resolve, reject) => {
fn(req, res, (result: any) => {
if (result instanceof Error) {
return reject(result);
}
return resolve(result);
});
});
}
/**
* @type {NextApiHandler}
*/
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// res.setHeader("Access-Control-Allow-Credentials", "true");
// res.setHeader("Access-Control-Allow-Origin", "*");
// res.setHeader("Access-Control-Allow-Methods", "*");
// res.setHeader("Access-Control-Allow-Headers", "*");
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("Access-Control-Allow-Origin", "*");
// another common pattern
// res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
res.setHeader("Access-Control-Allow-Methods", "GET,OPTIONS,PATCH,DELETE,POST,PUT");
res.setHeader("Access-Control-Allow-Headers", "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version");
// await runMiddleware(req, res, cors);
res.json({
title: "Hello There",
message: "General Kenobi",
});
}
import { NextApiHandler, NextApiRequest, NextApiResponse } from "next";
import Cors from "cors";
const cors = Cors({
methods: ["GET"],
origin: "*",
});
// Helper method to wait for a middleware to execute before continuing
// And to throw an error when an error happens in a middleware
function runMiddleware(req: NextApiRequest, res: NextApiResponse, fn: Function) {
return new Promise((resolve, reject) => {
fn(req, res, (result: any) => {
if (result instanceof Error) {
return reject(result);
}
return resolve(result);
});
});
}
/**
* @type {NextApiHandler}
*/
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// res.setHeader("Access-Control-Allow-Credentials", "true");
// res.setHeader("Access-Control-Allow-Origin", "*");
// res.setHeader("Access-Control-Allow-Methods", "*");
// res.setHeader("Access-Control-Allow-Headers", "*");
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("Access-Control-Allow-Origin", "*");
// another common pattern
// res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
res.setHeader("Access-Control-Allow-Methods", "GET,OPTIONS,PATCH,DELETE,POST,PUT");
res.setHeader("Access-Control-Allow-Headers", "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version");
// await runMiddleware(req, res, cors);
res.json({
title: "Hello There",
message: "General Kenobi",
});
}
+178 -178
View File
@@ -1,178 +1,178 @@
/**
* ==============================================================================
* Imports
* ==============================================================================
*/
import React from "react";
import Head from "next/head";
import type { InferGetStaticPropsType, GetStaticProps, GetStaticPaths } from "next";
const datasquirel = require("datasquirel");
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
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 }: InferGetStaticPropsType<typeof getStaticProps>) {
// ## Get Contexts
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## Javascript Variables
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## React Hooks { useState, useEffect, useRef, etc ... }
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## Function Return
return (
<React.Fragment>
<Head>
<title>{blogPost.title} | Tben.me Blog</title>
<meta
name="description"
content={blogPost.excerpt}
/>
</Head>
<GeneralLayout>
<div className="flex flex-col items-start gap-2 mb-8 max-w-6xl w-full">
<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.excerpt} />
</span>
<span className="text-base opacity-50">
<TextShuffler textInput={blogPost.date_created.substring(0, 24)} />
</span>
</div>
<span
className="flex flex-col items-start max-w-6xl w-full gap-4 text-xl"
dangerouslySetInnerHTML={{ __html: blogPost.body }}
></span>
</GeneralLayout>
</React.Fragment>
);
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
}
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/**
* Server Side Props or Static Props
* ==============================================================================
*/
export const getStaticProps: GetStaticProps = async ({ params }) => {
// ## Environment processes
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## User Authentication
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## Page/Site Data Data Fetching
const postsResponse = await datasquirel.get({
key: process.env.DATASQUIREL_API_KEY,
db: "tbenme",
query: `select * from blog_posts WHERE slug='${params?.single}'`,
});
const post = postsResponse.payload[0];
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## Server Props Return
return {
props: {
blogPost: post,
},
revalidate: 3600,
};
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
};
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/**
* Server Side Props or Static Props
* ==============================================================================
*/
export const getStaticPaths: GetStaticPaths = async () => {
/**
* Data fetching
*
* @abstract fetch date from the server or externnal source
*/
const postsResponse = await datasquirel.get({
key: process.env.DATASQUIREL_API_KEY,
db: "tbenme",
query: `select slug from blog_posts`,
});
const posts: { slug: string }[] | null = postsResponse.payload;
const paths = posts?.map((entry) => {
return {
params: { single: entry.slug },
};
});
return {
paths: paths ? paths : [],
fallback: "blocking",
};
};
/**
* ==============================================================================
* Imports
* ==============================================================================
*/
import React from "react";
import Head from "next/head";
import type { InferGetStaticPropsType, GetStaticProps, GetStaticPaths } from "next";
const datasquirel = require("datasquirel");
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
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 }: InferGetStaticPropsType<typeof getStaticProps>) {
// ## Get Contexts
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## Javascript Variables
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## React Hooks { useState, useEffect, useRef, etc ... }
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## Function Return
return (
<React.Fragment>
<Head>
<title>{blogPost.title} | Tben.me Blog</title>
<meta
name="description"
content={blogPost.excerpt}
/>
</Head>
<GeneralLayout>
<div className="flex flex-col items-start gap-2 mb-8 max-w-6xl w-full">
<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.excerpt} />
</span>
<span className="text-base opacity-50">
<TextShuffler textInput={blogPost.date_created.substring(0, 24)} />
</span>
</div>
<span
className="flex flex-col items-start max-w-6xl w-full gap-4 text-xl"
dangerouslySetInnerHTML={{ __html: blogPost.body }}
></span>
</GeneralLayout>
</React.Fragment>
);
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
}
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/**
* Server Side Props or Static Props
* ==============================================================================
*/
export const getStaticProps: GetStaticProps = async ({ params }) => {
// ## Environment processes
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## User Authentication
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## Page/Site Data Data Fetching
const postsResponse = await datasquirel.get({
key: process.env.DATASQUIREL_API_KEY,
db: "tbenme",
query: `select * from blog_posts WHERE slug='${params?.single}'`,
});
const post = postsResponse.payload[0];
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
// ## Server Props Return
return {
props: {
blogPost: post,
},
revalidate: 3600,
};
/** ********************************************** */
/** ********************************************** */
/** ********************************************** */
};
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/** ****************************************************************************** */
/**
* Server Side Props or Static Props
* ==============================================================================
*/
export const getStaticPaths: GetStaticPaths = async () => {
/**
* Data fetching
*
* @abstract fetch date from the server or externnal source
*/
const postsResponse = await datasquirel.get({
key: process.env.DATASQUIREL_API_KEY,
db: "tbenme",
query: `select slug from blog_posts`,
});
const posts: { slug: string }[] | null = postsResponse.payload;
const paths = posts?.map((entry) => {
return {
params: { single: entry.slug },
};
});
return {
paths: paths ? paths : [],
fallback: "blocking",
};
};
+39 -39
View File
@@ -1,39 +1,39 @@
import React from "react";
import Head from "next/head";
import TextShuffler from "../components/actions/TextShuffler";
import submitContactForm from "../functions/frontend/submitContactForm";
import GeneralLayout from "../layouts/general_layout/GeneralLayout";
import threeJsAnimations from "../functions/frontend/threeJsAnimations";
import ContactForm from "../app/(components)/ContactForm";
const contact = () => {
let [success, setSuccess] = React.useState(false);
return (
<GeneralLayout>
<Head>
<title>Contact me</title>
<meta
name="description"
content="Get in touch"
/>
</Head>
<div className="flex flex-col items-start max-w-6xl w-full">
<h1>
<TextShuffler textInput="Get in touch" />
</h1>
<span className="hero-sub-text">
<TextShuffler
textInput="Have a question? Want to work together? Send me a message!"
delay={500}
/>
</span>
<ContactForm />
</div>
</GeneralLayout>
);
};
export default contact;
import React from "react";
import Head from "next/head";
import TextShuffler from "../components/actions/TextShuffler";
import submitContactForm from "../functions/frontend/submitContactForm";
import GeneralLayout from "../layouts/general_layout/GeneralLayout";
import threeJsAnimations from "../functions/frontend/threeJsAnimations";
import ContactForm from "../app/(components)/ContactForm";
const contact = () => {
let [success, setSuccess] = React.useState(false);
return (
<GeneralLayout>
<Head>
<title>Contact me</title>
<meta
name="description"
content="Get in touch"
/>
</Head>
<div className="flex flex-col items-start max-w-6xl w-full">
<h1>
<TextShuffler textInput="Get in touch" />
</h1>
<span className="hero-sub-text">
<TextShuffler
textInput="Have a question? Want to work together? Send me a message!"
delay={500}
/>
</span>
<ContactForm />
</div>
</GeneralLayout>
);
};
export default contact;
+54 -54
View File
@@ -1,54 +1,54 @@
import React from "react";
import Head from "next/head";
import TextShuffler from "../components/actions/TextShuffler";
import GeneralLayout from "../layouts/general_layout/GeneralLayout";
import PortfolioEntry from "../components/PortfolioEntry";
const myWork = () => {
const portfolioEntries = require("../components/portfolioEntries.json");
return (
<GeneralLayout>
<Head>
<title>My Work | Tben</title>
<meta
name="description"
content="Some of my Work"
/>
</Head>
<div className="flex flex-col items-start w-full max-w-6xl">
<h1>
<TextShuffler textInput="My Work" />
</h1>
<span className="hero-sub-text mb-2">
<TextShuffler
textInput="Some of the projects I've worked on"
delay={500}
/>
</span>
<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}
/>
))}
</div>
</div>
</GeneralLayout>
);
};
export default myWork;
// {
// "title": "Stirrmedia Social webapp",
// "description": "A new social media experience without censorship",
// "url": "https://stirrmedia.com",
// "image": "/images/stirrmediascreenshot.png"
// },
import React from "react";
import Head from "next/head";
import TextShuffler from "../components/actions/TextShuffler";
import GeneralLayout from "../layouts/general_layout/GeneralLayout";
import PortfolioEntry from "../components/PortfolioEntry";
const myWork = () => {
const portfolioEntries = require("../components/portfolioEntries.json");
return (
<GeneralLayout>
<Head>
<title>My Work | Tben</title>
<meta
name="description"
content="Some of my Work"
/>
</Head>
<div className="flex flex-col items-start w-full max-w-6xl">
<h1>
<TextShuffler textInput="My Work" />
</h1>
<span className="hero-sub-text mb-2">
<TextShuffler
textInput="Some of the projects I've worked on"
delay={500}
/>
</span>
<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}
/>
))}
</div>
</div>
</GeneralLayout>
);
};
export default myWork;
// {
// "title": "Stirrmedia Social webapp",
// "description": "A new social media experience without censorship",
// "url": "https://stirrmedia.com",
// "image": "/images/stirrmediascreenshot.png"
// },