initial commit

This commit is contained in:
silva guimaraes 2025-04-21 17:59:57 -03:00
commit c21f569144
37 changed files with 3956 additions and 0 deletions

256
views/template.templ Normal file
View file

@ -0,0 +1,256 @@
package views
import (
"foobar/database"
"foobar/model"
"fmt"
"time"
)
templ indexLayout() {
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<title>Mude meu título!</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="htmx-config" content='{ "responseHandling":[{"code":"422", "swap": true}, {"code":"200", "swap": true}] }' />
<!-- tailwind -->
<link href="/static/css/output.css" rel="stylesheet"/>
<!-- markdown styling -->
<link href="/static/css/github-markdown.css" rel="stylesheet"/>
<!-- daisyUI -->
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css" />
<!-- daisyUI Themes -->
<link href="https://cdn.jsdelivr.net/npm/daisyui@5/themes.css" rel="stylesheet" type="text/css" />
// <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<!-- HTMX -->
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
<!-- Hyperscript -->
<script src="https://unpkg.com/hyperscript.org@0.9.14"></script>
<style>
html, body {
min-height: 100vh;
}
</style>
</head>
<body class="flex-wrap flex content-center justify-between flex-col bg-base-100 text-sm"
hx-boost="true" hx-push-url="true" hx-target="this">
{ children... }
<footer></footer>
</body>
</html>
}
templ mainCenterBody() {
@indexLayout() {
<main class="w-full" >
{ children... }
</main>
}
}
const toggleButtonInMeUntilLoad =
`on every htmx:beforeSend
tell <button/> in me
toggle [@disabled='true'] until htmx:afterOnLoad
end
end`
func safeURL(s string) string {
return fmt.Sprint(templ.SafeURL(s))
}
templ Index() {
@mainCenterBody() {
<div class="hero-content">
<div class="max-w-md text-center">
<h1>hakobox</h1>
<p>nothing here...</p>
</div>
</div>
}
}
templ boxUploadSidebar(boxURL model.BoxURL) {
@mainCenterBody() {
<div class="">
<section class="static md:fixed top-0 left-0 z-10 w-full md:w-3/9 p-10 bg-base-200 h-full ">
<header>
<h1>hakobox</h1>
<p>It's temporary file sharing but everyone gets to contribute! </p>
<p class="leading-tight font-medium text-black">Drop in a file to be added to this box </p>
</header>
<form id="add-file"
hx-trigger="submit"
hx-post={safeURL(fmt.Sprintf("/box/%s", boxURL))}
hx-encoding="multipart/form-data">
<fieldset class="fieldset">
<legend class="fieldset-legend">Pick a file</legend>
<input name="file" type="file" class="file-input" style="width: 100%;" multiple required/>
<label class="fieldset-label">Max size 2MB</label>
</fieldset>
<fieldset class="fieldset">
<legend class="fieldset-legend">Edit code</legend>
<input type="text" class="input" name="edit_code" placeholder="Type here" style="width: 100%;"/>
<p class="label">Optional</p>
</fieldset>
@errorTarget()
<button type="submit" class="btn btn-primary mb-5">Add to the box!</button>
<div class="text-center">
<a class="link link-primary block mb-0"
href={templ.SafeURL(fmt.Sprintf("/box/%s/inside", boxURL))}>
See what's inside
</a>
<a class="link link-primary block mb-0"
href={templ.SafeURL(fmt.Sprintf("/box/%s", boxURL))}>
Front page
</a>
</div>
</form>
</section>
<section class="md:px-20 p-4 md:my-40 m-0 md:ml-auto md:max-w-6/9">
{ children... }
</section>
</div>
}
}
templ BoxUpload(box model.Box) {
@boxUploadSidebar(box.Url()) {
<div class="markdown-body">
@templ.Raw(box.Header())
</div>
}
}
templ NewBox(boxURL model.BoxURL, templateReadme model.Markdown) {
@boxUploadSidebar(boxURL) {
<div class="markdown-body">
@templ.Raw(templateReadme)
</div>
}
}
templ Box(boxURL model.BoxURL, files []model.File) {
@boxUploadSidebar(boxURL) {
<main class="inline-flex flex-wrap gap-0 md:gap-5 mt-20 w-full h-full justify-start md:justify-center">
if len(files) == 0 {
<h2 class="m-auto">Empty box.</h2>
} else {
for i := range files {
@fileCard(files[i])
}
}
</main>
}
}
func fileDisplay(file model.File) templ.Component {
switch {
case file.Mime().IsImage():
return fileImageFigure(file)
case file.Mime().IsVideo():
return fileVideoFigure(file)
default:
return unknownFileFigure()
// panic(fmt.Errorf("unrecognized mime: %s", file.Mime))
}
}
templ fileCard(file model.File) {
<a class="card w-1/2 md:w-2xs aspect-square mb-10" href={templ.SafeURL(fmt.Sprintf("/static/box/%s", file.ID()))} target="_blank">
<figure class="flex flex-col p-1 m-auto mb-auto md:mb-0 text-center">
@fileDisplay(file)
</figure>
<div class="hidden md:inline font-light text-sm" style="text-wrap: nowrap;">
<p title={file.Name()}>{shorten(file.Name())}</p>
<p title={file.Name()}>{file.CreatedAt().Format(time.DateOnly)}</p>
<p>{formatSize(file.Size())} {file.Mime().PrettyType()}</p>
</div>
</a>
}
templ fileImageFigure(file model.File) {
<img
title={file.Name()}
loading="lazy"
src={fmt.Sprintf("/static/box/%s", file.ID())}
alt={file.Name()} />
}
templ fileVideoFigure(file model.File) {
<video title={file.Name()} loading="lazy" alt={file.Name()} >
<source src={fmt.Sprintf("/static/box/%s", file.ID())}/>
</video>
}
templ unknownFileFigure() {
<div>unknown format!</div>
}
func shorten(text string) string {
if len(text) > 41 {
return fmt.Sprintf("%s...", text[:41-3])
} else {
return text
}
}
func formatSize(size int64) string {
units := []string{"b", "Kb", "Mb", "Gb"}
i := 0
fSize := float64(size)
for fSize >= 1000 && i < len(units)-1 {
fSize /= 1000
i++
}
return fmt.Sprintf("%.2f %s", fSize, units[i])
}
templ FourOfour() {
@indexLayout() {
<div>404</div>
}
}
templ Logged(usuario *database.Usuario) {
@indexLayout() {
<p>Logado como: { usuario.Nome }</p>
<div style="text-align: center;">
<p>
<a href="/">index</a>
</p>
<p>
<a href="/logout">logout</a>
</p>
</div>
}
}
templ errorTarget() {
<div id="error-target">
</div>
}
templ ErrorBox(msg string) {
<div role="alert" class="bounce mt-3 relative flex flex-col w-full p-3 text-sm text-white bg-red-600 rounded-md">
<p class="flex text-base">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="h-5 w-5 mr-2 mt-0.5"><path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"></path></svg>
Error
</p>
<p class="ml-4 p-3">
{ msg }
</p>
<button class="flex items-center justify-center transition-all w-8 h-8 rounded-md text-white hover:bg-white/10 active:bg-white/10 absolute top-1.5 right-1.5" type="button"
_='on click tell closest <div[role="alert"]/> transition opacity to 0 then remove yourself end'
>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" class="h-5 w-5" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path></svg>
</button>
</div>
}