Compare commits
No commits in common. "0af01290540776bd0a23dc68af66b458980aac38" and "fa11926642d913946a4e4979509dd8ae0f562b02" have entirely different histories.
0af0129054
...
fa11926642
|
@ -25,4 +25,4 @@ run: $(GENERATED_FILES) $(OUTPUT_CSS)
|
|||
# and then do `go run .` to rebuild all else
|
||||
.PHONY: run/live
|
||||
run/live:
|
||||
wgo -verbose -file=.go -file=.templ -file=$(INPUT_CSS) -file=$(TAILWIND_CONFIG) make run
|
||||
wgo -verbose -file=.go -file=.templ make run
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
rec {
|
||||
description = "expenses chart exercise";
|
||||
description = "templ-practice";
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
|
@ -11,55 +11,7 @@ rec {
|
|||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
templPkg = templ.packages.${system}.templ;
|
||||
pname = "expenses-chart";
|
||||
version = "0.0.1";
|
||||
in rec {
|
||||
thePackage = pkgs.buildGoModule {
|
||||
inherit pname version;
|
||||
src = pkgs.nix-gitignore.gitignoreSource [ ] ./.;
|
||||
vendorHash = "sha256-sKuP3TsRD3MXBGtdSRnX62eXBQE1ASWFQu0kLlXSlFA=";
|
||||
|
||||
preBuild = ''
|
||||
# Adding the Tailwind build step to preBuild
|
||||
${pkgs.nodePackages.tailwindcss}/bin/tailwindcss -i ./input.css -o static/output.css
|
||||
# Adding generation of go code from templ files
|
||||
${templPkg}/bin/templ generate
|
||||
'';
|
||||
|
||||
};
|
||||
packages = rec {
|
||||
"${pname}" = thePackage;
|
||||
"${pname}-image" = pkgs.dockerTools.buildLayeredImage {
|
||||
name = pname;
|
||||
tag = "latest";
|
||||
created = "now";
|
||||
config = {
|
||||
Cmd = [ "${thePackage}/bin/templ-exercise" ];
|
||||
ExposedPorts = { "3000/tcp" = { }; };
|
||||
};
|
||||
};
|
||||
image-hello = pkgs.dockerTools.buildLayeredImage { # so, wow, this works
|
||||
name = pname;
|
||||
tag = "latest";
|
||||
config.Cmd = [ "${pkgs.hello}/bin/hello" ];
|
||||
};
|
||||
|
||||
image = pkgs.dockerTools.buildImage {
|
||||
name = pname;
|
||||
tag = "latest";
|
||||
created = "now";
|
||||
copyToRoot = pkgs.buildEnv {
|
||||
name = "image-root";
|
||||
paths = [ thePackage pkgs.dockerTools.binSh pkgs.coreutils ];
|
||||
pathsToLink = [ "/bin" "/dist" "/public" ];
|
||||
};
|
||||
config = {
|
||||
Cmd = [ "/bin/templ-exercise" ];
|
||||
ExposedPorts = { "8080/tcp" = { }; };
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
in {
|
||||
devShells.default = pkgs.mkShell {
|
||||
buildInputs = [
|
||||
pkgs.go
|
||||
|
@ -68,7 +20,7 @@ rec {
|
|||
pkgs.gopls
|
||||
pkgs.gnumake
|
||||
templPkg
|
||||
pkgs.nodePackages.tailwindcss
|
||||
pkgs.tailwindcss
|
||||
];
|
||||
shellHook = ''
|
||||
export GOPATH=$PWD/.go
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
html {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
|
|
@ -1,29 +1,17 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
|
||||
"sunshine.industries/temp-exercise/templates"
|
||||
"github.com/a-h/templ"
|
||||
)
|
||||
|
||||
func randomDailyExpense() float32 {
|
||||
return 10 + rand.Float32()*100
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
component := templates.IndexPage(templates.PageData{
|
||||
Balance: 500 + rand.Float32()*1000,
|
||||
Expenses: []float32{randomDailyExpense(), randomDailyExpense(), randomDailyExpense(), randomDailyExpense(), randomDailyExpense(), randomDailyExpense(), randomDailyExpense()},
|
||||
TotalThisMonth: 50 + rand.Float32()*600,
|
||||
PercentComparedToLastMonth: -5 + 10*rand.Float32(),
|
||||
})
|
||||
component.Render(context.Background(), w)
|
||||
})
|
||||
component := templates.Hello("some name")
|
||||
|
||||
http.Handle("/", templ.Handler(component))
|
||||
|
||||
staticFs := http.FileServer(http.Dir("./static"))
|
||||
http.Handle("/static/", http.StripPrefix("/static/", staticFs))
|
||||
|
|
|
@ -34,74 +34,3 @@ how would i commit to subtree upstream if there are conflicting changes?
|
|||
maybe i'll just get denied, as simple as that.
|
||||
|
||||
allright! let's add exercise specific data (again)
|
||||
|
||||
* so, starting dev
|
||||
|
||||
old process:
|
||||
1. open second browser and open png with style
|
||||
first mobile
|
||||
2. enable view C-S-m in firefox
|
||||
the responsive mode
|
||||
|
||||
i suppose next is adding colors to tailwind configuration?
|
||||
from the styleguide file
|
||||
|
||||
also
|
||||
3. check desktop style, whether any big rearrangements are required
|
||||
so that i'd start mobile with way to rearrange things
|
||||
|
||||
do i have a separate note with all of these things?
|
||||
i've also used some commands to vertically center my stuff
|
||||
|
||||
** DONE allright, tailwind config go
|
||||
font, size, colors
|
||||
|
||||
** well, i don't really want to go on.
|
||||
but yeah, i'll need hierarchy of the elements.
|
||||
|
||||
** ok. thoughs:
|
||||
the componets would be
|
||||
- my balance bubble
|
||||
because it is spacially separate
|
||||
- spending summary
|
||||
- graph inside spending summary
|
||||
or maybe don't even need that
|
||||
|
||||
the component should take up all space provided to it.
|
||||
if parent would want to add space around - that's easy to do,
|
||||
but if component insists on adding space around itself - harder to reuse?
|
||||
because then if parent would want to have child take up all space - negative padding?
|
||||
|
||||
*** allright, @ to include sub templates
|
||||
|
||||
** well, last part? preparing the docker container for deployment on Render.com?
|
||||
|
||||
which port should be used?
|
||||
also, this would be first time i'll add templ as a build step
|
||||
|
||||
** for some reason image doesn't work well
|
||||
|
||||
podman run -d -p 9090:8080 localhost/expenses-chart:latest /nix/store/l4r6glmzbvkhg97lp4dn7nm76w6hz41g-expenses-chart-0.0.1/bin/temp-exercise
|
||||
|
||||
this runs,
|
||||
but podman run -it expenses-chart:latest
|
||||
Error: crun: executable file `/nix/store/l4r6glmzbvkhg97lp4dn7nm76w6hz41g-expenses-chart-0.0.1/bin/templ-exercise` not found in $PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found
|
||||
|
||||
oh, well
|
||||
|
||||
** you know what - i give up
|
||||
|
||||
for some reason when i open url to app running in container,
|
||||
and it's on the 8080 port of the host machine - the static files are served
|
||||
|
||||
if i use any other port of local machine, to forward into container,
|
||||
the static files are not served
|
||||
|
||||
maybe this is bug in go? i don't know
|
||||
StripPrefix doesn't seem to do anything
|
||||
|
||||
and for some reason in this specific exercise CMD doesn't work in the container
|
||||
so let's just give up!
|
||||
|
||||
i could try to write a docker file and check with that, but yeah
|
||||
|
||||
|
|
|
@ -1,28 +1,8 @@
|
|||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["./templates/index.templ"],
|
||||
content: ["./**/*.templ"],
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
'sans': ['DM Sans', 'sans-serif'],
|
||||
},
|
||||
fontWeight: {
|
||||
'normal': 400,
|
||||
'bold': 700,
|
||||
}
|
||||
},
|
||||
colors: {
|
||||
primary: {
|
||||
'soft-red': 'hsl(10, 79%, 65%)',
|
||||
cyan: 'hsl(186, 34%, 60%)',
|
||||
},
|
||||
neutral: {
|
||||
'dark-brown': 'hsl(25, 47%, 15%)',
|
||||
'medium-brown': 'hsl(28, 10%, 53%)',
|
||||
cream: 'hsl(27, 66%, 92%)',
|
||||
'very-pale-orange': 'hsl(33, 100%, 98%)',
|
||||
},
|
||||
}
|
||||
extend: {},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package templates
|
||||
|
||||
var myVar string = "some string, changed. and more"
|
||||
var anotherVar string = "hoho, cool"
|
||||
|
||||
templ Hello(name string) {
|
||||
<html>
|
||||
<head>
|
||||
<title>This is the title of the the webpage!</title>
|
||||
<link href="/static/output.css" rel="stylesheet"/>
|
||||
</head>
|
||||
<body class="bg-blue-100 text-xl">
|
||||
<p class="text-purple-700">This is an example paragraph. Anything in the <strong>body</strong> tag will appear on the page, just like this <strong>p</strong> tag and its contents.</p>
|
||||
</body>
|
||||
</html>
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- displays site properly based on user's device -->
|
||||
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="./images/favicon-32x32.png">
|
||||
|
||||
<title>Frontend Mentor | Expenses chart component</title>
|
||||
|
||||
<!-- Feel free to remove these styles or customise in your own stylesheet 👍 -->
|
||||
<style>
|
||||
.attribution { font-size: 11px; text-align: center; }
|
||||
.attribution a { color: hsl(228, 45%, 44%); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
My balance
|
||||
$921.48
|
||||
|
||||
Spending - Last 7 days
|
||||
|
||||
mon
|
||||
tue
|
||||
wed
|
||||
thu
|
||||
fri
|
||||
sat
|
||||
sun
|
||||
|
||||
Total this month
|
||||
$478.33
|
||||
|
||||
+2.4%
|
||||
from last month
|
||||
|
||||
<div class="attribution">
|
||||
Challenge by <a href="https://www.frontendmentor.io?ref=challenge" target="_blank">Frontend Mentor</a>.
|
||||
Coded by <a href="#">Your Name Here</a>.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,133 +0,0 @@
|
|||
package templates
|
||||
|
||||
import "fmt"
|
||||
import "slices"
|
||||
|
||||
type PageData struct {
|
||||
Balance float32
|
||||
Expenses []float32
|
||||
TotalThisMonth float32
|
||||
PercentComparedToLastMonth float32
|
||||
}
|
||||
|
||||
templ myBalanceComponent(balance float32) {
|
||||
<div class="flex flex-row rounded-xl text-neutral-very-pale-orange text-xs md:text-base bg-primary-soft-red p-4 shadow md:rounded-[1rem] md:p-7">
|
||||
<div class="grow ">
|
||||
My balance
|
||||
<p class="text-xl md:text-2xl font-bold">${ fmt.Sprintf("%.2f", balance) }</p>
|
||||
</div>
|
||||
<img
|
||||
src="./static/images/logo.svg"
|
||||
alt="App logo: a white circle overlapping from the left a filled in black circle"
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
var days []string = []string{"mon", "tue", "wed", "thu", "fri", "sat", "sun"}
|
||||
|
||||
// returns templ SummaryComponent
|
||||
// with all attributes computed from the expenses slice
|
||||
// the percentages of the columns, current day number, etc
|
||||
// NOTE: this seems to be the way to mix go calculations and templates
|
||||
func prepareSummaryComponent(expenses []float32, totalThisMonth, percentComparedToLastMonth float32) templ.Component {
|
||||
fmt.Println("hello, preparing expenses: ", expenses)
|
||||
max := slices.Max(expenses)
|
||||
percentages := make([]float32, 0, len(expenses))
|
||||
for _, price := range expenses {
|
||||
percentages = append(percentages, price/max)
|
||||
}
|
||||
|
||||
currentDayNum := 2
|
||||
|
||||
return spendingSummaryComponent(expenses, percentages, currentDayNum, percentComparedToLastMonth, totalThisMonth)
|
||||
}
|
||||
|
||||
css expenseBarVars(percentage float32) {
|
||||
--height-percentage: { fmt.Sprintf("%.2f", percentage) };
|
||||
height: calc(var(--height-percentage) * 8rem);
|
||||
}
|
||||
|
||||
templ dayExpenseColumn(expense, percentage float32, day string, isCurrentDay bool) {
|
||||
<div class="flex flex-col justify-end items-center h-32">
|
||||
<div
|
||||
class={ "rounded group relative w-full h-12",
|
||||
expenseBarVars(percentage),
|
||||
templ.KV("bg-primary-soft-red hover:bg-primary-soft-red/70", !isCurrentDay),
|
||||
templ.KV("bg-primary-cyan hover:bg-primary-cyan/70", isCurrentDay),
|
||||
"hover:cursor-pointer" }
|
||||
>
|
||||
<span class="absolute left-1/2 -translate-x-1/2 -translate-y-7 opacity-0 group-hover:opacity-100 bg-neutral-dark-brown text-neutral-cream rounded text-xs p-1">${ fmt.Sprintf("%.2f", expense ) }</span>
|
||||
</div>
|
||||
<p class="text-neutral-medium-brown text-xs py-2">{ day }</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
// The 7 vertical bars of the per-day expenses
|
||||
templ expensesChart(expenses, percentages []float32, currentDayNum int) {
|
||||
<div class="grid grid-cols-7 place-content-between gap-x-3">
|
||||
for i := 0; i < 7; i++ {
|
||||
@dayExpenseColumn(expenses[i], percentages[i], days[i], currentDayNum == i)
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
// Big container with chard and total expenses of the week
|
||||
templ spendingSummaryComponent(expenses, percentages []float32, currentDayNum int, totalThisMonth, percentComparedToLastMonth float32) {
|
||||
<div class="bg-neutral-very-pale-orange rounded-xl shadow p-4 py-6 flex flex-col gap-y-4 md:p-7 md:px-10 md:rounded-[1rem] md:gap-y-5">
|
||||
<p2 class="text-neutral-dark-brown text-xl font-bold pb-6 md:text-2xl md:pb-12 ">Spending - Last 7 days</p2>
|
||||
@expensesChart(expenses, percentages, currentDayNum)
|
||||
<hr class="bg-neutral-cream border-t-0 h-0.5"/>
|
||||
<div class="grid grid-cols-2 text-sm text-neutral-medium-brown">
|
||||
<p class="col-span-full">Total this month</p>
|
||||
<div class="grow">
|
||||
<p class="grid items-center text-neutral-dark-brown text-2xl font-bold h-full md:text-4xl md:py-2">$ { fmt.Sprintf("%.2f", totalThisMonth) }</p>
|
||||
</div>
|
||||
<div class="text-right grid content-center">
|
||||
<div class="text-neutral-dark-brown font-bold ">
|
||||
if (percentComparedToLastMonth > 0) {
|
||||
<span class="inline">+</span>
|
||||
}
|
||||
{ fmt.Sprintf("%.2f", percentComparedToLastMonth) }%
|
||||
</div>
|
||||
from last month
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ WidgetsComponend(pageData PageData) {
|
||||
<div class="flex flex-col gap-4">
|
||||
@myBalanceComponent(pageData.Balance)
|
||||
@prepareSummaryComponent(pageData.Expenses, pageData.PercentComparedToLastMonth, pageData.TotalThisMonth)
|
||||
</div>
|
||||
}
|
||||
|
||||
templ IndexPage(pageData PageData) {
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com"/>
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&display=swap" rel="stylesheet"/>
|
||||
<link rel="stylesheet" href="/styles/templ.css"/>
|
||||
<link href="/static/output.css" rel="stylesheet"/>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <!-- displays site properly based on user's device -->
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="./static/images/favicon-32x32.png"/>
|
||||
<title>Frontend Mentor | Expenses chart component</title>
|
||||
<!-- Feel free to remove these styles or customise in your own stylesheet 👍 -->
|
||||
<style>
|
||||
.attribution { font-size: 11px; text-align: center; }
|
||||
.attribution a { color: hsl(228, 45%, 44%); }
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-neutral-cream text-bold p-4 h-full grid place-items-center">
|
||||
<main class="w-full md:w-1/4">
|
||||
@WidgetsComponend(pageData)
|
||||
</main>
|
||||
<div class="attribution fixed bottom-0 inset-x-0">
|
||||
Challenge by <a href="https://www.frontendmentor.io?ref=challenge" target="_blank">Frontend Mentor</a>.
|
||||
Coded by <a href="#">Your Name Here</a>.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
}
|
Loading…
Reference in New Issue