Updated user pages

This commit is contained in:
Borna Rajković committed 2023-12-31 13:35:29 +01:00
1 parent af2d0f03c6
commit 7a64afd767
26 files changed
+427 -105

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
.idea/** .idea/**
holiday-api holiday-api
.env .env
**/.DS_Store
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
+203
View File
@@ -0,0 +1,203 @@
body {
border: 0;
margin: 0;
padding: 0;
font-size: 20px;
}
main {
background: #f3ebe6;
width: 640px;
max-width: 100%;
position: relative;
}
.dialog {
box-sizing: border-box;
border: 1px solid #e0e0e0;
background: white;
margin: auto;
padding: 16px 32px;
}
.background-image {
min-width: 100vw;
min-height: 100vh;
max-width: 100vw;
max-height: 100vh;
background: url("/assets/background.jpg");
background-position: bottom;
background-size: cover;
}
@font-face {
font-family: Quicksand;
src: url(fonts/Quicksand-Light.ttf);
font-weight: 100 200;
}
@font-face {
font-family: Quicksand;
src: url(fonts/Quicksand-Medium.ttf);
font-weight: 300 300;
}
@font-face {
font-family: Quicksand;
src: url(fonts/Quicksand-Regular.ttf);
font-weight: 400 500;
}
@font-face {
font-family: Quicksand;
src: url(fonts/Quicksand-Bold.ttf);
font-weight: 800 900;
}
@font-face {
font-family: Quicksand;
src: url(fonts/Quicksand-SemiBold.ttf);
font-weight: 600 700;
}
* {
font-family: Quicksand, Arial, sans-serif;
}
h1 {
font-size: 2rem;
}
h1 a {
all: unset;
}
.form-field {
width: 100%;
margin-bottom: 16px;
}
.form-field label {
display: block;
color: #999;
}
.form-field input {
width: 300px;
border: none;
border-bottom: 1px solid #bbb;
font-size: 20px;
outline: none;
}
.form-field input:focus {
color: cadetblue;
border-bottom: 1px solid cadetblue;
}
.form-field input:not(focus) {
color: #333;
}
.form-field label {
display: block;
color: #999;
}
.form-field select {
all: unset;
width: 100%;
border: none;
border-bottom: 1px solid #bbb;
font-size: 20px;
outline: none;
}
.form-field select:focus {
color: cadetblue;
border-bottom: 1px solid cadetblue;
}
.form-field select:not(focus) {
color: #333;
}
.form-field:focus-within label {
color: cadetblue;
}
.button.secondary, button.primary {
padding: 12px 16px;
background-color: cadetblue;
font-family: Quicksand, Arial, sans-serif;
border: none;
color: white;
font-size: 1.2rem;
margin-top: 16px;
}
.button.secondary, button.primary:hover {
filter: contrast(140%);
}
.button.secondary, button.secondary {
padding: 12px 16px;
background-color: white;
font-family: Quicksand, Arial, sans-serif;
border: 1px solid cadetblue;
color: cadetblue;
font-size: 1.2rem;
margin-top: 16px;
}
.button.secondary:hover, button.secondary:hover {
filter: contrast(140%);
}
/*index.html*/
.search-dialog {
position: absolute;
top: 0;
left: 0;
width: 100%;
padding-bottom: 40px;
}
@media screen and (min-width: 480px) {
.search-dialog {
position: absolute;
top: 50%;
left: 10vw;
transform: translateY(-50%);
width: 380px;
padding-bottom: 40px;
}
}
/*results.html*/
.results-dialog {
position: relative;
width: 100%;
max-width: 100%;
padding-bottom: 40px;
}
.results-dialog table {
width: 100%;
}
.results-dialog table th, .results-dialog table td {
text-align: left;
}
@media screen and (min-width: 480px) {
.results-dialog {
position: relative;
margin: auto;
width: 600px;
padding-bottom: 40px;
}
}
.results td {
padding: 0.4em 0;
}
+20 -1
View File
@@ -1,6 +1,19 @@
const dialogContainerId = "#dialog-container" const dialogContainerId = "#dialog-container"
window.addEventListener('load', () => { window.addEventListener('load', () => {
document.querySelectorAll(".dropdown").forEach(el => {
const action = el.querySelector(".dropdown-action");
const content = el.querySelector(".dropdown-content");
console.log(action, content, el.offsetWidth, content.offsetWidth);
action.addEventListener('click', () => {
content.classList.toggle('selected');
console.log(content.offsetWidth - action.offsetWidth);
content.style.marginLeft = `-${(content.offsetWidth - action.offsetWidth)}px`;
})
})
// configure radio button groups // configure radio button groups
document.querySelectorAll("section.radio-group").forEach(el => { document.querySelectorAll("section.radio-group").forEach(el => {
const submittedInput = el.querySelector("input[type=hidden]"); const submittedInput = el.querySelector("input[type=hidden]");
@@ -23,7 +36,13 @@ window.addEventListener('load', () => {
let response = await fetch(btn.dataset.url); let response = await fetch(btn.dataset.url);
if(response.ok) { if(response.ok) {
response = await response.text(); response = await response.text();
const container = document.querySelector(dialogContainerId); let container = document.querySelector(dialogContainerId);
if(container == null) {
const node = document.createElement('div');
node.id = "dialog-container";
document.querySelector("body").appendChild(node);
container = document.querySelector(dialogContainerId);
}
container.innerHTML = response; container.innerHTML = response;
const dialogReference = document.querySelector(selector); const dialogReference = document.querySelector(selector);
dialogReference?.showModal(); dialogReference?.showModal();
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+28 -8
View File
@@ -1,5 +1,11 @@
/* cleanup */ /* cleanup */
:root {
--primary: #9222dd;
--primary-darker: #6400a2;
--primary-contrast: #eee;
}
* { * {
box-sizing: border-box; box-sizing: border-box;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
@@ -10,22 +16,26 @@
header { header {
padding: 1rem 2rem; padding: 1rem 2rem;
width: 100%; width: 100%;
background: #666; background: var(--primary);
color: var(--primary-contrast);
} }
header h1 { header h1 {
font-size: 1.25em; font-size: 1.25em;
} }
header a { header a {
color: #fff; color: var(--primary-contrast);
text-decoration: none; text-decoration: none;
} }
button { button {
all: unset; all: unset;
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
background: #dddddd; color: var(--primary-contrast);
border: solid 1px #cccccc; background: var(--primary);
border: solid 1px var(--primary-darker);
border-radius: 0.25em; border-radius: 0.25em;
font-size: 0.875em; font-size: 0.875em;
--text: var(--primary-contrast);
} }
select { select {
all: unset; all: unset;
@@ -63,6 +73,10 @@ nav a.selected, nav button.selected {
color: white; color: white;
} }
table {
border-radius: 0.5em;
}
table:not(.clean) { table:not(.clean) {
width: 100%; width: 100%;
} }
@@ -71,7 +85,8 @@ table th, table td {
text-align: left; text-align: left;
} }
table { table {
border-collapse: collapse; border-spacing: 0;
/*border-collapse: collapse;*/
} }
table thead * { table thead * {
background: #666; background: #666;
@@ -184,9 +199,9 @@ section.radio-group div input:checked+label {
color: white; color: white;
} }
img.icon { img.icon, button.icon svg {
height: 1.5em; height: 1.2em;
width: 1.5em; width: 1.2em;
} }
button.icon, a.icon { button.icon, a.icon {
display: flex; display: flex;
@@ -194,6 +209,11 @@ button.icon, a.icon {
gap: 0.3em; gap: 0.3em;
} }
button.icon svg, button.icon svg * {
fill: var(--text, var(--primary-contrast));
color: var(--text, var(--primary-contrast));
stroke: var(--text, var(--primary-contrast));
}
main { main {
display: flex; display: flex;
+17 -2
View File
@@ -1,12 +1,15 @@
package main package main
import ( import (
"bytes"
"encoding/csv"
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"holiday-api/holiday" "holiday-api/holiday"
"net/http" "net/http"
"strconv"
"time" "time"
) )
@@ -26,9 +29,9 @@ func getHolidays(service holiday.HolidayService) gin.HandlerFunc {
holidays, err := service.Find(search, paging) holidays, err := service.Find(search, paging)
if err != nil { if err != nil {
render(c, http.StatusNotFound, ErrorResponse{Created: time.Now(), Message: "failed fetching holidays"}) render(c, http.StatusNotFound, ErrorResponse{Created: time.Now(), Message: "failed fetching holidays"}, nil)
} else { } else {
render(c, http.StatusOK, mapHolidays(holidays)) render(c, http.StatusOK, mapHolidays(holidays), search.Type)
} }
} }
} }
@@ -54,6 +57,18 @@ type HolidayResponse struct {
Holidays []HolidayItemResponse `json:"holidays"` Holidays []HolidayItemResponse `json:"holidays"`
} }
func (h HolidayResponse) CSV() []byte {
buffer := bytes.Buffer{}
csvWriter := csv.NewWriter(&buffer)
csvWriter.Write([]string{"id", "date", "name", "description", "isStateHoliday", "isReligiousHoliday"})
for _, item := range h.Holidays {
csvWriter.Write([]string{item.Id.String(), item.Date.String(), item.Name, item.Description, strconv.FormatBool(item.IsStateHoliday), strconv.FormatBool(item.IsReligiousHoliday)})
}
csvWriter.Flush()
return buffer.Bytes()
}
type HolidayItemResponse struct { type HolidayItemResponse struct {
XMLName xml.Name `json:"-" xml:"Holiday"` XMLName xml.Name `json:"-" xml:"Holiday"`
Id uuid.UUID `json:"id" xml:"id,attr"` Id uuid.UUID `json:"id" xml:"id,attr"`
+1
View File
@@ -34,6 +34,7 @@ type Search struct {
RangeEnd *time.Time `form:"range_end" time_format:"2006-01-02"` RangeEnd *time.Time `form:"range_end" time_format:"2006-01-02"`
StateHoliday string `form:"state_holiday,omitempty" binding:"omitempty"` StateHoliday string `form:"state_holiday,omitempty" binding:"omitempty"`
ReligiousHoliday string `form:"religious_holiday,omitempty" binding:"omitempty"` ReligiousHoliday string `form:"religious_holiday,omitempty" binding:"omitempty"`
Type *string `form:"type,omitempty" binding:"omitempty"`
} }
func (s Search) IsStateHoliday() *bool { func (s Search) IsStateHoliday() *bool {
+20 -4
View File
@@ -62,16 +62,20 @@ func main() {
setupAdminDashboard(g.Group("/admin"), holidayService, countryService, yearService) setupAdminDashboard(g.Group("/admin"), holidayService, countryService, yearService)
g.GET("/", func(c *gin.Context) { g.GET("/", func(c *gin.Context) {
year := time.Now().Year() search := holiday.Search{Country: "HR", Year: nil}
search := holiday.Search{Country: "HR", Year: &year}
if err := c.ShouldBindQuery(&search); err != nil { if err := c.ShouldBindQuery(&search); err != nil {
c.AbortWithError(http.StatusBadRequest, err) c.AbortWithError(http.StatusBadRequest, err)
return return
} }
holidays, _ := holidayService.Find(search, holiday.Paging{PageSize: 100})
countries, _ := countryService.Find() countries, _ := countryService.Find()
years, _ := yearService.Find() years, _ := yearService.Find()
c.HTML(http.StatusOK, "index.gohtml", gin.H{"Years": years, "Countries": countries, "Search": search, "Holidays": mapHolidays(holidays).Holidays}) if search.Year == nil {
c.HTML(http.StatusOK, "index.gohtml", gin.H{"Years": years, "Countries": countries, "Search": search})
return
}
holidays, _ := holidayService.Find(search, holiday.Paging{PageSize: 100})
c.HTML(http.StatusOK, "results.gohtml", gin.H{"Years": years, "Countries": countries, "Search": search, "Holidays": mapHolidays(holidays).Holidays})
}) })
g.GET("/documentation", func(c *gin.Context) { g.GET("/documentation", func(c *gin.Context) {
countries, _ := countryService.Find() countries, _ := countryService.Find()
@@ -113,9 +117,11 @@ func loadTemplates(g *gin.Engine) {
} }
return false return false
}, },
"importSvg": IncludeHTML,
}) })
g.LoadHTMLFiles( g.LoadHTMLFiles(
"templates/index.gohtml", "templates/index.gohtml",
"templates/results.gohtml",
"templates/search.gohtml", "templates/search.gohtml",
"templates/documentation.gohtml", "templates/documentation.gohtml",
@@ -132,6 +138,16 @@ func loadTemplates(g *gin.Engine) {
) )
} }
func IncludeHTML(path string) template.HTML {
b, err := os.ReadFile(path)
if err != nil {
log.Println("includeHTML - error reading file: %v", err)
return ""
}
return template.HTML(string(b))
}
func setupAdminDashboard(adminDashboard *gin.RouterGroup, service holiday.HolidayService, countryService holiday.CountryService, yearService holiday.YearService) { func setupAdminDashboard(adminDashboard *gin.RouterGroup, service holiday.HolidayService, countryService holiday.CountryService, yearService holiday.YearService) {
adminDashboard.Use(gin.BasicAuth(loadAuth())) adminDashboard.Use(gin.BasicAuth(loadAuth()))
+25 -3
View File
@@ -4,12 +4,34 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
func render[T any](c *gin.Context, status int, response T) { type CSV interface {
switch c.GetHeader("accept") { CSV() []byte
}
func render(c *gin.Context, status int, response any, contentType *string) {
value := c.GetHeader("accept")
if contentType != nil {
switch *contentType {
case "xml":
value = "text/xml"
case "json":
value = "application/json"
case "csv":
value = "text/csv"
}
}
switch value {
case "text/csv":
if csvResponse, ok := response.(CSV); ok {
c.Data(200, value+"; charset=utf-8", csvResponse.CSV())
} else {
c.Header("content-type", "application/json; charset=utf-8")
c.JSON(status, response)
}
case "application/xml": case "application/xml":
fallthrough fallthrough
case "text/xml": case "text/xml":
c.Header("content-type", c.GetHeader("accept")+"; charset=utf-8") c.Header("content-type", value+"; charset=utf-8; header=present;")
c.XML(status, response) c.XML(status, response)
case "application/json": case "application/json":
fallthrough fallthrough
+5 -5
View File
@@ -61,7 +61,7 @@
</section> </section>
<section class="actions"> <section class="actions">
<button class="icon primary" type="submit"> <button class="icon primary" type="submit">
<img class="icon" src="/assets/images/search.svg"> {{ importSvg "/assets/icons/search.svg"}}
<span>Search</span> <span>Search</span>
</button> </button>
</section> </section>
@@ -85,11 +85,11 @@
<tr> <tr>
<td>{{$entry.Name}}</td> <td>{{$entry.Name}}</td>
<td>{{$entry.Date.Format "2006-01-02"}}</td> <td>{{$entry.Date.Format "2006-01-02"}}</td>
<td><img class="icon" src="{{if $entry.IsStateHoliday}}/assets/images/done-v.svg{{else}}/assets/images/close-x.svg{{end}}"></td> <td><img class="icon" src="{{if $entry.IsStateHoliday}}/assets/icons/done-v.svg{{else}}/assets/icons/close-x.svg{{end}}"></td>
<td><img class="icon" src="{{if $entry.IsReligiousHoliday}}/assets/images/done-v.svg{{else}}/assets/images/close-x.svg{{end}}"></td> <td><img class="icon" src="{{if $entry.IsReligiousHoliday}}/assets/icons/done-v.svg{{else}}/assets/icons/close-x.svg{{end}}"></td>
<td> <td>
<button data-type="dialog" data-trigger="#update-card" data-url="/admin/dialogs/edit-holiday?id={{$entry.Id}}" class="icon"><img class="icon" src="/assets/images/edit.svg"></button> <button data-type="dialog" data-trigger="#update-card" data-url="/admin/dialogs/edit-holiday?id={{$entry.Id}}" class="icon"><img class="icon" src="/assets/icons/edit.svg"></button>
<button data-type="dialog" data-trigger="#delete-card" data-url="/admin/dialogs/delete-holiday?id={{$entry.Id}}" class="icon"><img class="icon" src="/assets/images/trash-delete.svg"></button> <button data-type="dialog" data-trigger="#delete-card" data-url="/admin/dialogs/delete-holiday?id={{$entry.Id}}" class="icon"><img class="icon" src="/assets/icons/trash-delete.svg"></button>
</td> </td>
</tr> </tr>
{{end}} {{end}}
+2 -2
View File
@@ -46,8 +46,8 @@
<td>{{$entry.IsoName}}</td> <td>{{$entry.IsoName}}</td>
<td>{{$entry.Name}}</td> <td>{{$entry.Name}}</td>
<td> <td>
<button type="button" data-type="dialog" data-trigger="#update-card" data-url="/admin/dialogs/edit-country?id={{$entry.Id}}" class="clean icon"><img class="icon" src="/assets/images/edit.svg"></button> <button type="button" data-type="dialog" data-trigger="#update-card" data-url="/admin/dialogs/edit-country?id={{$entry.Id}}" class="clean icon"><img class="icon" src="/assets/icons/edit.svg"></button>
<button type="button" data-type="dialog" data-trigger="#delete-card" data-url="/admin/dialogs/delete-country?id={{$entry.Id}}" class="clean icon"><img class="icon" src="/assets/images/trash-delete.svg"></button> <button type="button" data-type="dialog" data-trigger="#delete-card" data-url="/admin/dialogs/delete-country?id={{$entry.Id}}" class="clean icon"><img class="icon" src="/assets/icons/trash-delete.svg"></button>
</td> </td>
</tr> </tr>
{{end}} {{end}}
+1 -1
View File
@@ -1,7 +1,7 @@
<dialog class="card" data-closeable id="check-is-a-holiday"> <dialog class="card" data-closeable id="check-is-a-holiday">
<div style="display: flex;"> <div style="display: flex;">
<h2 style="margin-right: 1em;">Is it a holiday?</h2> <h2 style="margin-right: 1em;">Is it a holiday?</h2>
<button onclick="closeDialog('#check-is-a-holiday')" class="clean icon"><img class="icon" src="/assets/images/close-x.svg"></button> <button onclick="closeDialog('#check-is-a-holiday')" class="clean icon"><img class="icon" src="/assets/icons/close-x.svg"></button>
</div> </div>
<form method="get" action="/search"> <form method="get" action="/search">
<section> <section>
+14 -77
View File
@@ -1,95 +1,32 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html>
<head> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Holiday-api</title> <title>Holiday-api</title>
<link rel="stylesheet" href="/assets/style.css"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/assets/global.css">
<script src="/assets/global.js"></script> <script src="/assets/global.js"></script>
</head> </head>
<body> <body>
<div id="dialog-container"></div> <div class="background-image">
<header> <article class="dialog search-dialog">
<section class="container">
<h1><a href="/">Holiday-api</a></h1> <h1><a href="/">Holiday-api</a></h1>
</section> <form action="/">
</header> <div class="form-field">
<nav> <label for="year">Za godinu:</label>
<section class="container">
<a class="selected" href="#">Search</a>
<a href="/documentation">Documentation</a>
<button data-type="dialog" data-trigger="#check-is-a-holiday" data-url="/dialogs/check-is-a-holiday">Check is a holiday</button>
</section>
</nav>
<main>
<section id="search">
<article class="card">
<form action="/" method="get">
<section>
<label for="country">Country:</label>
<select id="country" name="country">
{{range $entry := .Countries}}
<option {{if eq $.Search.Country $entry.IsoName}}selected{{end}} value="{{$entry.IsoName}}">{{$entry.Name}}</option>
{{end}}
</select>
</section>
<section>
<label for="year">Year:</label>
<select id="year" name="year"> <select id="year" name="year">
{{range $entry := .Years}} {{range $entry := .Years}}
<option {{if intpeq $.Search.Year $entry}}selected{{end}} value="{{$entry}}">{{$entry}}</option> <option {{if intpeq $.Search.Year $entry}}selected{{end}} value="{{$entry}}">{{$entry}}</option>
{{end}} {{end}}
</select> </select>
</section>
<section class="radio-group">
<label>Is state holiday:</label>
<div>
<input type="radio" value="true" name="sh" id="sh_true"><label for="sh_true">True
</label><input type="radio" value="false" name="sh" id="sh_false"><label for="sh_false">False
</label><input type="radio" value="" name="sh" id="sh_any"><label for="sh_any">All</label>
</div> </div>
<input type="hidden" value="{{.Search.StateHoliday}}" name="state_holiday"> <div class="button-actions">
</section> <button class="primary">Pretraži</button>
<section class="radio-group">
<label>Is religious holiday:</label>
<div>
<input type="radio" value="true" name="rh" id="rh_true"><label for="rh_true">True
</label><input type="radio" value="false" name="rh" id="rh_false"><label for="rh_false">False
</label><input type="radio" value="" name="rh" id="rh_any"><label for="rh_any">All</label>
</div> </div>
<input type="hidden" value="{{.Search.ReligiousHoliday}}" name="religious_holiday">
</section>
<section class="actions">
<button class="icon primary" type="submit">
<img class="icon" src="/assets/images/search.svg">
<span>Search</span>
</button>
</section>
</form> </form>
</article> </article>
</section> </div>
<section id="results">
<table>
<thead>
<tr>
<th>Name</th>
<th>Date</th>
<th>State</th>
<th>Religious</th>
</tr>
</thead>
<tbody>
{{range $entry := .Holidays}}
<tr>
<td>{{$entry.Name}}</td>
<td>{{$entry.Date.Format "2006-01-02"}}</td>
<td><img class="icon" src="{{if $entry.IsStateHoliday}}/assets/images/done-v.svg{{else}}/assets/images/close-x.svg{{end}}"></td>
<td><img class="icon" src="{{if $entry.IsReligiousHoliday}}/assets/images/done-v.svg{{else}}/assets/images/close-x.svg{{end}}"></td>
</tr>
{{end}}
</tbody>
</table>
</section>
</main>
</body> </body>
</html> </html>
+88
View File
@@ -0,0 +1,88 @@
<!DOCTYPE html>
<html>
<head>
<title>Holiday-api | {{deferint $.Search.Year}}</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="/assets/global.css">
<script src="/assets/global.js"></script>
<style>
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
.dropdown-content.selected {
display: block;
}
.dropdown-content a {
all: unset;
display: block;
padding: 0.5em 1em;
}
.dropdown-content a:hover {
background: rgba(95, 158, 160, 0.2);
}
</style>
</head>
<body>
<div class="background-image" style="position: fixed;"></div>
<article class="dialog results-dialog">
<section style="margin-bottom: 1em;">
<h1><a href="/">Holiday-api</a> | {{deferint $.Search.Year}}</h1>
<form style="display: flex; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 1em" action="/">
<div style="flex-grow: 1;"></div>
<div class="form-field" style="width: auto;" >
<label for="year">Za godinu:</label>
<select id="year" name="year" style="width: 150px">
{{range $entry := .Years}}
<option {{if intpeq $.Search.Year $entry}}selected{{end}} value="{{$entry}}">{{$entry}}</option>
{{end}}
</select>
</div>
<div class="button-actions">
<button class="primary">Pretraži</button>
</div>
<div class="button-actions" style="margin-left: auto">
<div class="dropdown">
<button type="button" class="secondary dropdown-action">Preuzmi</button>
<div class="dropdown-content">
<a target="_blank" href="/api/v1/holidays?country=HR&type=csv&year={{deferint $.Search.Year}}">Kao csv</a>
<a target="_blank" href="/api/v1/holidays?country=HR&type=json&year={{deferint $.Search.Year}}">Kao json</a>
<a target="_blank" href="/api/v1/holidays?country=HR&type=xml&year={{deferint $.Search.Year}}">Kao xml</a>
</div>
</div>
</div>
</form>
</section>
<table class="results">
<thead>
<tr>
<th>Ime</th>
<th>Datum</th>
</tr>
</thead>
<tbody>
{{range $entry := .Holidays}}
<tr>
<td>{{$entry.Name}}</td>
<td>{{$entry.Date.Format "02.01.2006."}}</td>
</tr>
{{end}}
</tbody>
</table>
</article>
</body>
</html>
+2 -2
View File
@@ -60,11 +60,11 @@
</tr> </tr>
<tr> <tr>
<th>Is state holiday: </th> <th>Is state holiday: </th>
<td><img class="icon" src="{{if $entry.IsStateHoliday}}/assets/images/done-v.svg{{else}}/assets/images/close-x.svg{{end}}"></td> <td><img class="icon" src="{{if $entry.IsStateHoliday}}/assets/icons/done-v.svg{{else}}/assets/images/close-x.svg{{end}}"></td>
</tr> </tr>
<tr> <tr>
<th>Is religious holiday: </th> <th>Is religious holiday: </th>
<td><img class="icon" src="{{if $entry.IsReligiousHoliday}}/assets/images/done-v.svg{{else}}/assets/images/close-x.svg{{end}}"></td> <td><img class="icon" src="{{if $entry.IsReligiousHoliday}}/assets/icons/done-v.svg{{else}}/assets/images/close-x.svg{{end}}"></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>