Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
DATABASE_DIALECT = "postgres"
DATABASE_HOST = "127.0.0.1"
DATABASE_PORT = "5432"
DATABASE_DATABASE = "defaultdb"
DATABASE_USERNAME = "postgres"
DATABASE_PASSWORD = "postgres"
DATABASE_SSL = "false"
DATABASE_SSL_CERT = ""
DATABASE_LOGGING = "false"
DATABASE_DIALECT = "postgres"
DATABASE_HOST = "127.0.0.1"
DATABASE_PORT = "5432"
DATABASE_DATABASE = "defaultdb"
DATABASE_USERNAME = "postgres"
DATABASE_PASSWORD = "postgres"
DATABASE_SSL = "false"
DATABASE_SSL_CERT = ""
DATABASE_LOGGING = "false"

HOST_URL = "http://localhost:3000"
BASE_PATH = ""
HOST_URL = "http://localhost:3000"
BASE_PATH = ""

GOOGLE_VERIFICATION = ""
GOOGLE_TAG_MANAGER_ID = ""
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
"editor.formatOnSave": true
},
"editor.tabSize": 2,
"cSpell.words": ["MERN", "portfolio", "tailwindcss"]
"cSpell.words": ["flowbite", "hoverable", "MERN", "portfolio", "tailwindcss"]
}
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
"@types/react-vertical-timeline-component": "^3.3.6",
"bcrypt": "^5.1.1",
"cli-highlight": "^2.1.11",
"dotenv": "^16.4.5",
"flowbite": "^2.3.0",
"flowbite-react": "^0.7.5",
"lodash": "^4.17.21",
"mariadb": "^3.3.0",
"mysql2": "^3.9.2",
Expand Down Expand Up @@ -68,7 +71,10 @@
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.5.11",
"tailwindcss": "^3.3.0",
"typescript": "^5.4.3"
"ts-loader": "^9.5.1",
"typescript": "^5.4.3",
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
},
"nextBundleAnalysis": {
"budget": 358400,
Expand Down
19 changes: 19 additions & 0 deletions src/admin/common/BreadCrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Breadcrumb } from 'flowbite-react';
import Link from 'next/link';

interface IBreadCrumbItem {
href: string;
name: string;
}

export default function BreadCrumb({ links }: { links: Array<IBreadCrumbItem> }) {
return (
<Breadcrumb className="mb-5">
{(links || []).map((link: IBreadCrumbItem, i) => (
<Breadcrumb.Item key={`breadcrumb-item-${i}`}>
<Link href={link.href}>{link.name}</Link>
</Breadcrumb.Item>
))}
</Breadcrumb>
);
}
93 changes: 93 additions & 0 deletions src/admin/common/MyTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
'use client';

import { i18n } from '@/i18n';
import { Checkbox, Table } from 'flowbite-react';

interface IHeader {
key: string;
label: string;
onClick?: Function;
order?: 'asc' | 'desc' | 'none';
}

interface ICell {
value: string;
onClick?: Function;
render?: Function;
}

interface IRow {
[key: string]: ICell | number | string;
}

interface ITables {
hasCheckBox?: boolean;
headers: Array<IHeader>;
hoverable?: boolean;
rows: Array<IRow>;
}

export default function MyTable(props: ITables) {
const { hoverable, headers, hasCheckBox, rows } = props;

const headerKeys = (headers || []).map((header: IHeader) => header.key);

const RenderCell = ({ props }: { props: ICell | number | string }) => {
const { value, onClick, render } =
typeof props === 'object' ? props : { value: props, onClick: undefined, render: undefined };
const content = (render && render.call(null, value)) || value;
return (
<span
onClick={(evt) => {
evt.stopPropagation();
evt.preventDefault();
onClick && onClick.call(null);
}}
>
{content}
</span>
);
};

return (
<div className="overflow-x-auto mb-5">
<Table className="text-md font-medium" hoverable={hoverable}>
<Table.Head>
{hasCheckBox && (
<Table.HeadCell className="p-4">
<Checkbox />
</Table.HeadCell>
)}
{(headers || []).map(({ key, label, onClick, order }: IHeader) => (
<Table.HeadCell
key={`table-header-${key}`}
onClick={(evt) => {
evt.stopPropagation();
evt.preventDefault();
onClick && onClick.call(null, key, order);
}}
>
{i18n(label)}
</Table.HeadCell>
))}
</Table.Head>
<Table.Body className="divide-y">
{(rows || []).map((row: IRow, i) => (
<Table.Row key={`table-row-${i}`} className="bg-white dark:border-gray-700 dark:bg-gray-800">
{hasCheckBox && (
<Table.Cell className="p-4">
<Checkbox />
</Table.Cell>
)}
{headerKeys.map((key) => (
<Table.Cell key={`table-row-${i}-${key}`}>
<RenderCell props={row[key]} />
</Table.Cell>
))}
</Table.Row>
))}
</Table.Body>
</Table>
</div>
);
}
99 changes: 51 additions & 48 deletions src/app/about/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { SNLightBulb } from '@icongo/sn';
import aboutImage from '@/app/assets/about.svg';
import Image from 'next/image';
import RootLayout from '@/components/layouts/RootLayout';
import Skills from '@/components/Skills';
import type { Metadata } from 'next';
import aboutImage from '@/app/assets/about.svg';

export const metadata: Metadata = {
title: "James Gates | I'm glad to meet you",
Expand All @@ -20,58 +21,60 @@ export const metadata: Metadata = {

export default function Page() {
return (
<section className="about container mx-auto px-2 sm:px-6 lg:px-8">
<div className="grid md:grid-cols-12 mt-28">
<div className="md:col-span-7 flex flex-col items-center">
<h1 className="pb-20 text-center text-4xl">
I&apos;m <strong className="text-impact">James Gates</strong>, really glad to meet{' '}
<strong className="text-impact">you</strong>
</h1>
<RootLayout>
<section className="about container mx-auto px-2 sm:px-6 lg:px-8">
<div className="grid md:grid-cols-12 mt-28">
<div className="md:col-span-7 flex flex-col items-center">
<h1 className="pb-20 text-center text-4xl">
I&apos;m <strong className="text-black dark:text-white">James Gates</strong>, really glad to meet{' '}
<strong className="text-black dark:text-white">you</strong>
</h1>

<p className="text-xl leading-8">
Hi, everyone, I&apos;m <span className="text-impact">James Gates</span>.<br />
I&apos;m <span className="text-impact">Senior Full Stack Developer</span> and{' '}
<span className="text-impact">SEO Expert</span>.
<br />
<br />I have 5+ years&apos; experience for web development. During last years, I had earned many skills to
develop and manage a website and it now helps for a new project to develop in a high quality, rapidly.
<br />
<br />I like to work with a simple communication, a clean and optimized code convention, a high quality
development for collaboration and maintenance, and a keeping schedules for a project. I also love learning a
new thing from analyzing, discussing and resolving variable claims.
</p>
</div>
<p className="text-xl leading-8">
Hi, everyone, I&apos;m <span className="text-black dark:text-white">James Gates</span>.<br />
I&apos;m <span className="text-black dark:text-white">Senior Full Stack Developer</span> and{' '}
<span className="text-black dark:text-white">SEO Expert</span>.
<br />
<br />I have 5+ years&apos; experience for web development. During last years, I had earned many skills to
develop and manage a website and it now helps for a new project to develop in a high quality, rapidly.
<br />
<br />I like to work with a simple communication, a clean and optimized code convention, a high quality
development for collaboration and maintenance, and a keeping schedules for a project. I also love learning
a new thing from analyzing, discussing and resolving variable claims.
</p>
</div>

<div className="md:col-span-5 flex items-center justify-center">
<Image
src={aboutImage}
alt="About"
className="w-auto max-h-[450px] mt-16"
width={600}
height={529}
title="About"
loading="lazy"
/>
<div className="md:col-span-5 flex items-center justify-center">
<Image
src={aboutImage}
alt="About"
className="w-auto max-h-[450px] mt-16"
width={600}
height={529}
title="About"
loading="lazy"
/>
</div>
</div>
</div>

<div className="text-4xl mt-24 flex flex-row justify-center gap-4">
<SNLightBulb />
<strong className="text-impact">Skills</strong>
</div>
<div className="text-4xl mt-24 flex flex-row justify-center gap-4">
<SNLightBulb />
<strong className="text-black dark:text-white">Skills</strong>
</div>

<Skills />
<Skills />

<div className="text-xl leading-8 lg:w-1/2 px-10 mt-28 mx-auto">
<p>
For many aspects, such as Requirement Analysis, Architect Design, Database Modeling, Front-end/Back-end Coding
and Maintenance, I support reliable and qualified service.
</p>
<ul className="list-disc list-inside ml-5">
<li>Fast Progress, Best Quality and Constant Report</li>
<li>Cooperative Idea Support and so on</li>
</ul>
</div>
</section>
<div className="text-xl leading-8 lg:w-1/2 px-10 mt-28 mx-auto">
<p>
For many aspects, such as Requirement Analysis, Architect Design, Database Modeling, Front-end/Back-end
Coding and Maintenance, I support reliable and qualified service.
</p>
<ul className="list-disc list-inside ml-5">
<li>Fast Progress, Best Quality and Constant Report</li>
<li>Cooperative Idea Support and so on</li>
</ul>
</div>
</section>
</RootLayout>
);
}
15 changes: 15 additions & 0 deletions src/app/admin/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import NavBar from '@/components/admin/NavBar';
import { Flowbite } from 'flowbite-react';

export default function AdminLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<Flowbite>
<NavBar />
<section className="container mx-auto">{children}</section>
</Flowbite>
);
}
50 changes: 50 additions & 0 deletions src/app/admin/user/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use client';

import { i18n } from '@/i18n';
import BreadCrumb from '@/admin/common/BreadCrumb';
import MyTable from '@/admin/common/MyTable';

export default function Page() {
return (
<div>
<BreadCrumb
links={[
{ href: '/', name: 'Home' },
{ href: '#', name: i18n('entities.user.title') },
]}
/>
<MyTable
headers={[
{ key: 'id', label: 'entities.user.fields.id' },
{ key: 'fullName', label: 'entities.user.fields.fullName' },
{ key: 'firstName', label: 'entities.user.fields.firstName' },
{ key: 'lastName', label: 'entities.user.fields.lastName' },
{ key: 'email', label: 'entities.user.fields.email' },
]}
rows={[
{
id: 1,
fullName: 'James Gates',
firstName: 'James',
lastName: 'Gates',
email: 'james.gates.0212@gmail.com',
},
{
id: 2,
fullName: 'James Gates',
firstName: {
value: 'James',
render: (value) => (
<span className="whitespace-nowrap font-medium text-gray-900 dark:text-white">{value}</span>
),
},
lastName: 'Gates',
email: 'pop.runner88@outlook.com',
},
]}
hasCheckBox
hoverable
/>
</div>
);
}
Binary file removed src/app/assets/background.jpg
Binary file not shown.
Binary file removed src/app/assets/background.webp
Binary file not shown.
25 changes: 14 additions & 11 deletions src/app/experience/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Metadata } from 'next';
import Experience from '@/components/clients/Experience';
import RootLayout from '@/components/layouts/RootLayout';
import type { Metadata } from 'next';

export const metadata: Metadata = {
title: 'James Gates | Experience & Education',
Expand All @@ -16,15 +17,17 @@ export const metadata: Metadata = {

export default function Page() {
return (
<section className="about container mx-auto px-2 sm:px-6 lg:px-8">
<h1 className="text-4xl leading-8 text-center mt-32">
<strong className="text-impact">Experience</strong>
<small> &amp; </small>
<strong className="text-impact">Education</strong>
</h1>
<div className="text-left mt-10">
<Experience />
</div>
</section>
<RootLayout>
<section className="about container mx-auto px-2 sm:px-6 lg:px-8">
<h1 className="text-4xl leading-8 text-center mt-32">
<strong className="text-black dark:text-white">Experience</strong>
<small> &amp; </small>
<strong className="text-black dark:text-white">Education</strong>
</h1>
<div className="text-left mt-10">
<Experience />
</div>
</section>
</RootLayout>
);
}
Loading