From 3f1c8cb6aaa22337cb331dc9de8ae1d2c509cbc1 Mon Sep 17 00:00:00 2001 From: Remy Moll <me@moll.re> Date: Mon, 13 May 2024 18:19:15 +0200 Subject: [PATCH] basic structure and a bit of content --- frontend/public/style.css | 533 +++++++++++++++++++++- frontend/src/{layout.tsx => base.tsx} | 4 +- frontend/src/components/footer.tsx | 20 + frontend/src/components/hero.tsx | 20 + frontend/src/components/navigation.tsx | 20 + frontend/src/components/timeline.tsx | 24 + frontend/src/components/timeline_card.tsx | 22 + frontend/src/index.tsx | 110 ++++- frontend/src/landing.tsx | 10 - frontend/src/pages/landing.tsx | 20 + frontend/src/pages/portfolio.tsx | 0 frontend/src/structs/footer_link.tsx | 7 + frontend/src/structs/timeline_item.tsx | 9 + 13 files changed, 772 insertions(+), 27 deletions(-) rename frontend/src/{layout.tsx => base.tsx} (84%) create mode 100644 frontend/src/components/footer.tsx create mode 100644 frontend/src/components/hero.tsx create mode 100644 frontend/src/components/navigation.tsx create mode 100644 frontend/src/components/timeline.tsx create mode 100644 frontend/src/components/timeline_card.tsx delete mode 100644 frontend/src/landing.tsx create mode 100644 frontend/src/pages/landing.tsx create mode 100644 frontend/src/pages/portfolio.tsx create mode 100644 frontend/src/structs/footer_link.tsx create mode 100644 frontend/src/structs/timeline_item.tsx diff --git a/frontend/public/style.css b/frontend/public/style.css index 1359831..ecb4bc4 100644 --- a/frontend/public/style.css +++ b/frontend/public/style.css @@ -544,18 +544,214 @@ video { --tw-backdrop-sepia: ; } +.container { + width: 100%; +} + +@media (min-width: 640px) { + .container { + max-width: 640px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 768px; + } +} + +@media (min-width: 1024px) { + .container { + max-width: 1024px; + } +} + +@media (min-width: 1280px) { + .container { + max-width: 1280px; + } +} + +@media (min-width: 1536px) { + .container { + max-width: 1536px; + } +} + +.static { + position: static; +} + +.fixed { + position: fixed; +} + +.absolute { + position: absolute; +} + +.relative { + position: relative; +} + +.sticky { + position: sticky; +} + +.-start-3 { + inset-inline-start: -0.75rem; +} + +.my-4 { + margin-top: 1rem; + margin-bottom: 1rem; +} + +.mx-2 { + margin-left: 0.5rem; + margin-right: 0.5rem; +} + +.mb-1 { + margin-bottom: 0.25rem; +} + +.mb-10 { + margin-bottom: 2.5rem; +} + +.mb-2 { + margin-bottom: 0.5rem; +} + +.mb-4 { + margin-bottom: 1rem; +} + +.me-2 { + margin-inline-end: 0.5rem; +} + +.me-2\.5 { + margin-inline-end: 0.625rem; +} + +.ms-3 { + margin-inline-start: 0.75rem; +} + +.ms-6 { + margin-inline-start: 1.5rem; +} + +.mt-4 { + margin-top: 1rem; +} + +.mr-3 { + margin-right: 0.75rem; +} + +.block { + display: block; +} + +.inline-block { + display: inline-block; +} + .flex { display: flex; } +.inline-flex { + display: inline-flex; +} + +.h-2 { + height: 0.5rem; +} + +.h-2\.5 { + height: 0.625rem; +} + +.h-3 { + height: 0.75rem; +} + +.h-3\.5 { + height: 0.875rem; +} + +.h-6 { + height: 1.5rem; +} + +.h-full { + height: 100%; +} + .h-screen { height: 100vh; } +.h-32 { + height: 8rem; +} + +.w-2 { + width: 0.5rem; +} + +.w-2\.5 { + width: 0.625rem; +} + +.w-3 { + width: 0.75rem; +} + +.w-3\.5 { + width: 0.875rem; +} + +.w-6 { + width: 1.5rem; +} + .w-screen { width: 100vw; } +.w-full { + width: 100%; +} + +@keyframes bounce { + 0%, 100% { + transform: translateY(-25%); + animation-timing-function: cubic-bezier(0.8,0,1,1); + } + + 50% { + transform: none; + animation-timing-function: cubic-bezier(0,0,0.2,1); + } +} + +.animate-bounce { + animation: bounce 1s infinite; +} + +.cursor-not-allowed { + cursor: not-allowed; +} + +.flex-row { + flex-direction: row; +} + .flex-col { flex-direction: column; } @@ -572,35 +768,366 @@ video { gap: 0.75rem; } +.gap-4 { + gap: 1rem; +} + .rounded { border-radius: 0.25rem; } +.rounded-full { + border-radius: 9999px; +} + +.rounded-lg { + border-radius: 0.5rem; +} + +.border { + border-width: 1px; +} + +.border-s { + border-inline-start-width: 1px; +} + +.border-gray-200 { + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); +} + +.border-blue-500 { + --tw-border-opacity: 1; + border-color: rgb(59 130 246 / var(--tw-border-opacity)); +} + +.border-white { + --tw-border-opacity: 1; + border-color: rgb(255 255 255 / var(--tw-border-opacity)); +} + +.bg-blue-100 { + --tw-bg-opacity: 1; + background-color: rgb(219 234 254 / var(--tw-bg-opacity)); +} + .bg-blue-500 { --tw-bg-opacity: 1; background-color: rgb(59 130 246 / var(--tw-bg-opacity)); } +.bg-white { + --tw-bg-opacity: 1; + background-color: rgb(255 255 255 / var(--tw-bg-opacity)); +} + +.bg-gray-200 { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + +.bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); +} + +.bg-gradient-to-r { + background-image: linear-gradient(to right, var(--tw-gradient-stops)); +} + +.from-purple-700 { + --tw-gradient-from: #7e22ce var(--tw-gradient-from-position); + --tw-gradient-to: rgb(126 34 206 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to); +} + +.via-blue-900 { + --tw-gradient-to: rgb(30 58 138 / 0) var(--tw-gradient-to-position); + --tw-gradient-stops: var(--tw-gradient-from), #1e3a8a var(--tw-gradient-via-position), var(--tw-gradient-to); +} + +.to-red-500 { + --tw-gradient-to: #ef4444 var(--tw-gradient-to-position); +} + +.p-4 { + padding: 1rem; +} + +.p-1 { + padding: 0.25rem; +} + +.p-5 { + padding: 1.25rem; +} + +.px-2 { + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.px-2\.5 { + padding-left: 0.625rem; + padding-right: 0.625rem; +} + .px-4 { padding-left: 1rem; padding-right: 1rem; } +.py-0 { + padding-top: 0px; + padding-bottom: 0px; +} + +.py-0\.5 { + padding-top: 0.125rem; + padding-bottom: 0.125rem; +} + .py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; } +.px-3 { + padding-left: 0.75rem; + padding-right: 0.75rem; +} + +.py-1 { + padding-top: 0.25rem; + padding-bottom: 0.25rem; +} + +.font-mono { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +.text-2xl { + font-size: 1.5rem; + line-height: 2rem; +} + +.text-6xl { + font-size: 3.75rem; + line-height: 1; +} + +.text-base { + font-size: 1rem; + line-height: 1.5rem; +} + +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + +.text-sm { + font-size: 0.875rem; + line-height: 1.25rem; +} + .font-bold { font-weight: 700; } +.font-medium { + font-weight: 500; +} + +.font-normal { + font-weight: 400; +} + +.font-semibold { + font-weight: 600; +} + +.leading-none { + line-height: 1; +} + +.text-black { + --tw-text-opacity: 1; + color: rgb(0 0 0 / var(--tw-text-opacity)); +} + +.text-blue-800 { + --tw-text-opacity: 1; + color: rgb(30 64 175 / var(--tw-text-opacity)); +} + +.text-gray-400 { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); +} + +.text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); +} + +.text-gray-900 { + --tw-text-opacity: 1; + color: rgb(17 24 39 / var(--tw-text-opacity)); +} + .text-white { --tw-text-opacity: 1; color: rgb(255 255 255 / var(--tw-text-opacity)); } -.hover\:bg-blue-700:hover { - --tw-bg-opacity: 1; - background-color: rgb(29 78 216 / var(--tw-bg-opacity)); +.text-blue-500 { + --tw-text-opacity: 1; + color: rgb(59 130 246 / var(--tw-text-opacity)); +} + +.shadow-md { + --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color); + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} + +.shadow-black\/5 { + --tw-shadow-color: rgb(0 0 0 / 0.05); + --tw-shadow: var(--tw-shadow-colored); +} + +.ring-8 { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.ring-white { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(255 255 255 / var(--tw-ring-opacity)); +} + +.hover\:border-gray-200:hover { + --tw-border-opacity: 1; + border-color: rgb(229 231 235 / var(--tw-border-opacity)); +} + +.hover\:bg-blue-600:hover { + --tw-bg-opacity: 1; + background-color: rgb(37 99 235 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(243 244 246 / var(--tw-bg-opacity)); +} + +.hover\:bg-gray-200:hover { + --tw-bg-opacity: 1; + background-color: rgb(229 231 235 / var(--tw-bg-opacity)); +} + +.hover\:text-blue-700:hover { + --tw-text-opacity: 1; + color: rgb(29 78 216 / var(--tw-text-opacity)); +} + +.hover\:text-gray-200:hover { + --tw-text-opacity: 1; + color: rgb(229 231 235 / var(--tw-text-opacity)); +} + +.focus\:z-10:focus { + z-index: 10; +} + +.focus\:text-blue-700:focus { + --tw-text-opacity: 1; + color: rgb(29 78 216 / var(--tw-text-opacity)); +} + +.focus\:outline-none:focus { + outline: 2px solid transparent; + outline-offset: 2px; +} + +.focus\:ring-4:focus { + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000); +} + +.focus\:ring-gray-100:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(243 244 246 / var(--tw-ring-opacity)); +} + +@media (min-width: 768px) { + .md\:p-3 { + padding: 0.75rem; + } +} + +@media (prefers-color-scheme: dark) { + .dark\:border-gray-600 { + --tw-border-opacity: 1; + border-color: rgb(75 85 99 / var(--tw-border-opacity)); + } + + .dark\:border-gray-700 { + --tw-border-opacity: 1; + border-color: rgb(55 65 81 / var(--tw-border-opacity)); + } + + .dark\:bg-blue-900 { + --tw-bg-opacity: 1; + background-color: rgb(30 58 138 / var(--tw-bg-opacity)); + } + + .dark\:bg-gray-800 { + --tw-bg-opacity: 1; + background-color: rgb(31 41 55 / var(--tw-bg-opacity)); + } + + .dark\:text-blue-300 { + --tw-text-opacity: 1; + color: rgb(147 197 253 / var(--tw-text-opacity)); + } + + .dark\:text-gray-400 { + --tw-text-opacity: 1; + color: rgb(156 163 175 / var(--tw-text-opacity)); + } + + .dark\:text-gray-500 { + --tw-text-opacity: 1; + color: rgb(107 114 128 / var(--tw-text-opacity)); + } + + .dark\:text-white { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); + } + + .dark\:ring-gray-900 { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(17 24 39 / var(--tw-ring-opacity)); + } + + .dark\:hover\:bg-gray-700:hover { + --tw-bg-opacity: 1; + background-color: rgb(55 65 81 / var(--tw-bg-opacity)); + } + + .dark\:hover\:text-white:hover { + --tw-text-opacity: 1; + color: rgb(255 255 255 / var(--tw-text-opacity)); + } + + .dark\:focus\:ring-gray-700:focus { + --tw-ring-opacity: 1; + --tw-ring-color: rgb(55 65 81 / var(--tw-ring-opacity)); + } } diff --git a/frontend/src/layout.tsx b/frontend/src/base.tsx similarity index 84% rename from frontend/src/layout.tsx rename to frontend/src/base.tsx index d48f7d7..baf318e 100644 --- a/frontend/src/layout.tsx +++ b/frontend/src/base.tsx @@ -1,6 +1,6 @@ import * as elements from "typed-html"; -const HomeLayout = ({ children }: elements.Children) => ` +const BaseHTML = ({ children }: elements.Children) => ` <head> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <script src="https://unpkg.com/htmx.org@1.9.5"></script> @@ -12,4 +12,4 @@ const HomeLayout = ({ children }: elements.Children) => ` </body> `; -export { HomeLayout } +export { BaseHTML } diff --git a/frontend/src/components/footer.tsx b/frontend/src/components/footer.tsx new file mode 100644 index 0000000..efd98b0 --- /dev/null +++ b/frontend/src/components/footer.tsx @@ -0,0 +1,20 @@ +import { FooterLink } from "../structs/footer_link"; + +const Footer = ({ footer_links }: {footer_links: FooterLink[]}) => { + return ( + <footer class={'w-full h-32 bg-gray-800 flex items-center justify-center'}> + {footer_links.map((link) => { + return ( + <a href={link.url} class={'mx-2'}> + <i class={`fas fa-${ + link.icon_name + } text-white`}></i> + </a> + ); + } + )} + </footer> + ); +} + +export { Footer } \ No newline at end of file diff --git a/frontend/src/components/hero.tsx b/frontend/src/components/hero.tsx new file mode 100644 index 0000000..996989b --- /dev/null +++ b/frontend/src/components/hero.tsx @@ -0,0 +1,20 @@ +const Hero = () => { + return ( + <div class="bg-gradient-to-r from-purple-700 via-blue-900 to-red-500 w-screen h-screen" id="hero"> + <div class="flex flex-col items-center justify-center h-full"> + <div class="text-6xl font-bold text-white">Welcome to <span class="font-mono">moll.re</span></div> + <div class="text-2xl text-white">An exciting journey!</div> + <button class="px-4 py-2 my-4 text-lg font-semibold text-white bg-blue-500 rounded hover:bg-blue-600"> + Explore + </button> + <div class="mt-4 animate-bounce"> + <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-white animate-bounce" fill="none" viewBox="0 0 24 24" stroke="currentColor"> + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3"></path> + </svg> + </div> + </div> + </div> + ); +}; + +export { Hero} \ No newline at end of file diff --git a/frontend/src/components/navigation.tsx b/frontend/src/components/navigation.tsx new file mode 100644 index 0000000..9e5aa0b --- /dev/null +++ b/frontend/src/components/navigation.tsx @@ -0,0 +1,20 @@ + +const Navigation = () => { + return( + <nav id={'header'} class={'flex-no-wrap sticky w-screen py-2 shadow-black/5'}> + <ul class="flex"> + <li class="mr-3"> + <a class="inline-block border border-blue-500 rounded py-1 px-3 bg-blue-500 text-white" href="#">Active Pill</a> + </li> + <li class="mr-3"> + <a class="inline-block border border-white rounded hover:border-gray-200 text-blue-500 hover:bg-gray-200 py-1 px-3" href="#">Pill</a> + </li> + <li class="mr-3"> + <a class="inline-block py-1 px-3 text-gray-400 cursor-not-allowed" href="#">Disabled Pill</a> + </li> + </ul> + </nav> + ); +}; + +export { Navigation } diff --git a/frontend/src/components/timeline.tsx b/frontend/src/components/timeline.tsx new file mode 100644 index 0000000..d65aa3c --- /dev/null +++ b/frontend/src/components/timeline.tsx @@ -0,0 +1,24 @@ +import * as elements from "typed-html"; +import { TimelineCard } from "./timeline_card"; +import { TimelineItem } from "../structs/timeline_item"; + +const Timeline = ({ timeline_items }: {timeline_items: TimelineItem[]}) => { + return ( + <div class={'container md:p-3'}> + <div class="flex flex-col items-center justify-center"> + <div class="text-6xl font-bold text-black">Timeline</div> + <div class="text-2xl text-black">A little about us</div> + <ol class="relative border-s border-gray-200 dark:border-gray-700"> + {timeline_items.map((item, index) => ( + // <div class={`card ${index % 2 === 0 ? 'left' : 'right'}`}> + <li class={`mb-10 ms-6 p-4 rounded-lg shadow-md ${index % 2 === 0 ? 'bg-white' : 'bg-gray-200'}`}> + <TimelineCard {...item}/> + </li> + ))} + </ol> + </div> + </div> + ); +}; + +export { Timeline } \ No newline at end of file diff --git a/frontend/src/components/timeline_card.tsx b/frontend/src/components/timeline_card.tsx new file mode 100644 index 0000000..dae5834 --- /dev/null +++ b/frontend/src/components/timeline_card.tsx @@ -0,0 +1,22 @@ +import * as elements from "typed-html"; + +import { TimelineItem } from "../structs/timeline_item"; + + + +const TimelineCard = ({ date_start, date_end, title, description, icon_name}: TimelineItem) => { + return ( + <div> + <span class="absolute flex items-center justify-center w-6 h-6 bg-blue-100 rounded-full -start-3 ring-8 ring-white dark:ring-gray-900 dark:bg-blue-900"> + <svg class="w-2.5 h-2.5 text-blue-800 dark:text-blue-300" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"> + <path d="M20 4a2 2 0 0 0-2-2h-2V1a1 1 0 0 0-2 0v1h-3V1a1 1 0 0 0-2 0v1H6V1a1 1 0 0 0-2 0v1H2a2 2 0 0 0-2 2v2h20V4ZM0 18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8H0v10Zm5-8h10a1 1 0 0 1 0 2H5a1 1 0 0 1 0-2Z"/> + </svg> + </span> + <h3 class="mb-1 text-lg font-semibold text-gray-900">{ title }</h3> + <time class="block mb-2 text-sm font-normal leading-none text-gray-400 dark:text-gray-500">{ date_start.toLocaleDateString() } - { date_end.toLocaleDateString() }</time> + <p class="text-base font-normal text-gray-500 dark:text-gray-400">{ description }</p> + </div> + ); +}; + +export { TimelineCard } \ No newline at end of file diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index a26a644..e198b32 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -2,26 +2,112 @@ import { Elysia } from "elysia"; import { html } from "@elysiajs/html"; import { staticPlugin } from "@elysiajs/static"; -// import { autoroutes } from "elysia-autoroutes"; -// import { Store } from "./store"; -// // @ts-ignore -// import data from "../package.json"; +import { BaseHTML } from "./base"; +import { LandingPage } from "./pages/landing"; -import { HomeLayout } from "./layout"; -import { Landing } from "./landing"; +import { TimelineItem } from "./structs/timeline_item"; +import { FooterLink } from "./structs/footer_link"; + +const timeline_items: TimelineItem[] = [ + { + date_start: new Date(), + date_end: new Date(), + title: "First", + description: "Description number 1", + icon_name: "world", + }, + { + date_start: new Date(), + date_end: new Date(), + title: "Hello", + description: "Description number 2", + icon_name: "world", + }, + { + date_start: new Date(), + date_end: new Date(), + title: "Hello", + description: "Longer description number 3", + icon_name: "world", + }, + { + date_start: new Date(), + date_end: new Date(), + title: "Hello", + description: "Very looooooooooong description number 4", + icon_name: "world", + }, + { + date_start: new Date(), + date_end: new Date(), + title: "Hello", + description: "Description number 5", + icon_name: "world", + }, + { + date_start: new Date(), + date_end: new Date(), + title: "Hello", + description: "Description number 6", + icon_name: "world", + }, + { + date_start: new Date(), + date_end: new Date(), + title: "Hello", + description: "Description number 7", + icon_name: "world", + }, + { + date_start: new Date(), + date_end: new Date(), + title: "Hello", + description: "Description number 8", + icon_name: "world", + }, +]; + + +const footer_links: FooterLink[] = [ + { + icon_name: "github", + title: "Github", + url: "https://github.com", + }, + { + icon_name: "twitter", + title: "Twitter", + url: "https://twitter.com", + }, + { + icon_name: "linkedin", + title: "LinkedIn", + url: "https://linkedin.com", + }, + { + icon_name: "instagram", + title: "Instagram", + url: "https://instagram.com", + }, + { + icon_name: "facebook", + title: "Facebook", + url: "https://facebook.com", + }, +]; + +const content = { + 'timeline_items': timeline_items, + 'footer_links': footer_links, +}; export const server = new Elysia() .use(html()) .use(staticPlugin()) - // .get("/public/htmx.js", () => - // Bun.file("node_modules/htmx.org/dist/htmx.min.js"), - // ) - // .state("store", new Store()) - // .state("version", data.version) .onError(({ code, error }) => { console.error(code, error); }) - .get("/", ({html}) => html(<HomeLayout><Landing></Landing></HomeLayout>)) + .get("/", ({html}) => html(<BaseHTML><LandingPage{content}/></BaseHTML>)) .post("/clicked", ()=> <div>Hello?</div>) .listen(Bun.env["PORT"] ?? 3000); diff --git a/frontend/src/landing.tsx b/frontend/src/landing.tsx deleted file mode 100644 index 136c1ad..0000000 --- a/frontend/src/landing.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import * as elements from "typed-html"; - -const Landing = ({ children }: elements.Children) => ` - <button hx-post="/clicked" hx-swap="outerHTML" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"> - Click me - </button> - ${children} -`; - -export { Landing } diff --git a/frontend/src/pages/landing.tsx b/frontend/src/pages/landing.tsx new file mode 100644 index 0000000..e358851 --- /dev/null +++ b/frontend/src/pages/landing.tsx @@ -0,0 +1,20 @@ +import * as elements from "typed-html"; +import { Timeline } from "../components/timeline"; +import { Navigation } from "../components/navigation"; +import { Hero } from "../components/hero"; +import { Footer } from "../components/footer"; + + +const LandingPage = ({ content }: Dict) => { + return ( + <div class={'w-full h-full'}> + <Hero /> + <Navigation /> + <Timeline {content['timeline_items']}/> + <Footer {content['footer_links']}/> + </div> + ); +}; + + +export { LandingPage } diff --git a/frontend/src/pages/portfolio.tsx b/frontend/src/pages/portfolio.tsx new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/structs/footer_link.tsx b/frontend/src/structs/footer_link.tsx new file mode 100644 index 0000000..eece29c --- /dev/null +++ b/frontend/src/structs/footer_link.tsx @@ -0,0 +1,7 @@ +type FooterLink = { + icon_name: string; + title: string; + url: string; +} + +export { FooterLink } \ No newline at end of file diff --git a/frontend/src/structs/timeline_item.tsx b/frontend/src/structs/timeline_item.tsx new file mode 100644 index 0000000..fe48452 --- /dev/null +++ b/frontend/src/structs/timeline_item.tsx @@ -0,0 +1,9 @@ +type TimelineItem = { + date_start: Date; + date_end: Date; + title: string; + description: string; + icon_name: string; +} + +export { TimelineItem }