diff options
Diffstat (limited to 'front/src/components')
| -rw-r--r-- | front/src/components/project.css | 137 | ||||
| -rw-r--r-- | front/src/components/project.tsx | 93 |
2 files changed, 230 insertions, 0 deletions
diff --git a/front/src/components/project.css b/front/src/components/project.css new file mode 100644 index 0000000..f9cc07f --- /dev/null +++ b/front/src/components/project.css @@ -0,0 +1,137 @@ +.icon { + display: inline; + width: 32px; + height: 32px; + transition: 0.3s; + transform-origin: center; + filter: brightness(70%) +} + +.icon:hover { + filter: brightness(80%); +} + +.icon-row { + width: 240px; + height: 36px; +} + +.icon-container { + height: 36px; + float: right; +} + +.icon-text { + width: auto; + height: 36px; + line-height: 36px; + float: left; + vertical-align: middle; + margin-right: 8px; + color: #5c6370; +} + +.projects-container { + width: 100%; + max-width: 1120px; + margin: auto; + margin-top: 24pt; + margin-bottom: 48pt; + align-items: center; + justify-content: center; + align-self: center; +} + +.project { + display: table; + align-self: center; + clear: both; + margin-bottom: 24pt; +} + +.project-info { + font-size: 14pt; +} + +.project-description { + font-size: 16pt; + text-align: justify; +} + +.project-image-gallery { + margin-left: 24px; + margin-right: 10px; +} + +@media (max-width: 1150px) { + .project-title { + text-align: center; + font-size: 24pt; + margin-bottom: 8px; + text-decoration-line: underline; + } + + .project-image-gallery { + margin: 60px auto; + width: 330px; + height: 220px; + } + + .project-info { + float: none; + width: 90%; + margin: auto; + } + + .project-description { + font-size: 14pt; + } +} + +@media (max-width: 1150px) and (min-width: 480px) { + .project-title { + text-align: center; + font-size: 24pt; + margin-bottom: 8px; + text-decoration-line: underline; + } + .project-image-gallery { + margin: 60px auto; + width: 480px; + height: 360px; + } + + .project-info { + float: none; + width: 90%; + margin: auto; + } + + .project-description { + font-size: 14pt; + } +} + +@media (min-width: 1150px) { + .project-title { + text-align: left; + font-size: 32pt; + margin-bottom: 8px; + text-decoration-line: underline; + } + .project-image-gallery { + float: right; + width: 480px; + height: 360px; + } + .project-info { + float: left; + max-width: 600px; + } + + .project-description { + font-size: 16pt; + } +} + + diff --git a/front/src/components/project.tsx b/front/src/components/project.tsx new file mode 100644 index 0000000..cb9496d --- /dev/null +++ b/front/src/components/project.tsx @@ -0,0 +1,93 @@ +import Carousel from "./carousel"; +import './project.css'; + +enum ProjectType { + GAME = "game", + PROJECT = "project", +} + +export enum ProjectTech { + CSHARP = "csharp", + RUST = "rust", + C = "c", + CPP = "cpp", + JAVASCRIPT = "javascript", + TYPESCRIPT = "typescript", + HTML = "html", + CSS = "css", + + PREACT = "preact", + UNITY = "unity", + GODOT = "godot", + MONOGAME = "monogame", +} + +export enum ProjectTarget { + WEB = "html5", + WINDOWS = "windows", + LINUX = "linux", + MACOS = "macos", + ANDROID = "android", + HYPRLAND = "hyprland", +} + +export interface ProjectDescriptor { + name: string; + name_normalized: string; + type: ProjectType; + link: string; + tech: ProjectTech[]; + targets: ProjectTarget[]; + images: string[]; + description: string; +} + +function getProjectImageLink(project: ProjectDescriptor, image: string) { + return `assets/${project.type}s/${project.name_normalized}/${image}`; +} + +function getProjectTechIconLink(tech: ProjectTech) { + return `assets/images/${tech}.png`; +} + +function getProjectTargetIconLink(target: ProjectTarget) { + return `assets/images/${target}.png`; +} + +export function Project(props: ProjectDescriptor) { + return ( + <div class="project"> + <div class="project-title"><a href={props.link}>{props.name}</a></div> + <div class="project-info"> + <div class="icon-row"> + <div class="icon-text">Made using</div> + <div class="icon-container"> + {props.tech.map((tech) => ( + <img class="grow icon" src={getProjectTechIconLink(tech)} /> + ))} + </div> + </div> + <div class="icon-row"> + <div class="icon-text">Available on</div> + <div class="icon-container"> + {props.targets.map((target) => ( + <img class="grow icon" src={getProjectTargetIconLink(target)} /> + ))} + </div> + </div> + <hr /> + <div class="project-description"> + { + // use description as html + <div dangerouslySetInnerHTML={{ __html: props.description }} /> + } + </div> + </div> + <Carousel> + {props.images.map((image) => ( + <img class="project-image" src={getProjectImageLink(props, image)} /> + ))} + </Carousel> + </div> + ); +} |
