Compare commits

...

4 Commits

Author SHA1 Message Date
99c2eec759 add some tests 2024-07-28 15:48:03 +02:00
623291541a Fixing redirects 2024-07-28 15:23:12 +02:00
d7f7a2d8d9 Handling Calendar changes 2024-07-28 14:43:39 +02:00
14828fb901 Reservation calendar 4 2024-07-28 13:59:54 +02:00
11 changed files with 271 additions and 68 deletions

View File

@ -44,10 +44,11 @@ func routes(app *config.AppConfig) http.Handler {
mux.Get("/reservations-new", handlers.Repo.AdminNewReservations) mux.Get("/reservations-new", handlers.Repo.AdminNewReservations)
mux.Get("/reservations-all", handlers.Repo.AdminAllReservations) mux.Get("/reservations-all", handlers.Repo.AdminAllReservations)
mux.Get("/reservations-calendar", handlers.Repo.AdminReservationsCalendar) mux.Get("/reservations-calendar", handlers.Repo.AdminReservationsCalendar)
mux.Get("/process-reservation/{src}/{id}", handlers.Repo.AdminProcessReservation) mux.Post("/reservations-calendar", handlers.Repo.AdminPostReservationsCalendar)
mux.Get("/delete-reservation/{src}/{id}", handlers.Repo.AdminDeleteReservation) mux.Get("/process-reservation/{src}/{id}/do", handlers.Repo.AdminProcessReservation)
mux.Get("/delete-reservation/{src}/{id}/do", handlers.Repo.AdminDeleteReservation)
mux.Get("/reservations/{src}/{id}", handlers.Repo.AdminShowReservation) mux.Get("/reservations/{src}/{id}/show", handlers.Repo.AdminShowReservation)
mux.Post("/reservations/{src}/{id}", handlers.Repo.AdminPostShowReservation) mux.Post("/reservations/{src}/{id}", handlers.Repo.AdminPostShowReservation)
}) })

View File

@ -83,14 +83,14 @@ func (m *Repository) MakeReservation(w http.ResponseWriter, r *http.Request) {
res, ok := m.App.Session.Get(r.Context(), "reservation").(models.Reservation) res, ok := m.App.Session.Get(r.Context(), "reservation").(models.Reservation)
if !ok { if !ok {
m.App.Session.Put(r.Context(), "error", "can't get reservation from session") m.App.Session.Put(r.Context(), "error", "can't get reservation from session")
http.Redirect(w, r, "/", http.StatusTemporaryRedirect) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
room, err := m.DB.GetRoomById(res.RoomID) room, err := m.DB.GetRoomById(res.RoomID)
if err != nil { if err != nil {
m.App.Session.Put(r.Context(), "error", "can't find room") m.App.Session.Put(r.Context(), "error", "can't find room")
http.Redirect(w, r, "/", http.StatusTemporaryRedirect) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
@ -118,13 +118,13 @@ func (m *Repository) PostMakeReservation(w http.ResponseWriter, r *http.Request)
reservation, ok := m.App.Session.Get(r.Context(), "reservation").(models.Reservation) reservation, ok := m.App.Session.Get(r.Context(), "reservation").(models.Reservation)
if !ok { if !ok {
m.App.Session.Put(r.Context(), "error", "can't get reservation from session") m.App.Session.Put(r.Context(), "error", "can't get reservation from session")
http.Redirect(w, r, "/", http.StatusTemporaryRedirect) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
m.App.Session.Put(r.Context(), "error", "can't parse form") m.App.Session.Put(r.Context(), "error", "can't parse form")
http.Redirect(w, r, "/", http.StatusTemporaryRedirect) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
@ -155,7 +155,7 @@ func (m *Repository) PostMakeReservation(w http.ResponseWriter, r *http.Request)
newReservationID, err := m.DB.InsertReservation(reservation) newReservationID, err := m.DB.InsertReservation(reservation)
if err != nil { if err != nil {
m.App.Session.Put(r.Context(), "error", "can't insert reservation into database") m.App.Session.Put(r.Context(), "error", "can't insert reservation into database")
http.Redirect(w, r, "/", http.StatusTemporaryRedirect) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
@ -173,7 +173,7 @@ func (m *Repository) PostMakeReservation(w http.ResponseWriter, r *http.Request)
err = m.DB.InsertRoomRestriction(restriction) err = m.DB.InsertRoomRestriction(restriction)
if err != nil { if err != nil {
m.App.Session.Put(r.Context(), "error", "can't insert room restriction into database") m.App.Session.Put(r.Context(), "error", "can't insert room restriction into database")
http.Redirect(w, r, "/", http.StatusTemporaryRedirect) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
@ -224,7 +224,7 @@ func (m *Repository) ReservationSummary(w http.ResponseWriter, r *http.Request)
if !ok { if !ok {
m.App.ErrorLog.Println("connot get item from session") m.App.ErrorLog.Println("connot get item from session")
m.App.Session.Put(r.Context(), "error", "Can't get reservation from session") m.App.Session.Put(r.Context(), "error", "Can't get reservation from session")
http.Redirect(w, r, "/", http.StatusTemporaryRedirect) http.Redirect(w, r, "/", http.StatusSeeOther)
} }
m.App.Session.Remove(r.Context(), "reservation") m.App.Session.Remove(r.Context(), "reservation")
@ -254,7 +254,7 @@ func (m *Repository) Availability(w http.ResponseWriter, r *http.Request) {
func (m *Repository) PostAvailability(w http.ResponseWriter, r *http.Request) { func (m *Repository) PostAvailability(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil { if err := r.ParseForm(); err != nil {
m.App.Session.Put(r.Context(), "error", "can't parse form") m.App.Session.Put(r.Context(), "error", "can't parse form")
http.Redirect(w, r, "/", http.StatusTemporaryRedirect) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }
start := r.Form.Get("start") start := r.Form.Get("start")
@ -264,20 +264,20 @@ func (m *Repository) PostAvailability(w http.ResponseWriter, r *http.Request) {
startDate, err := time.Parse(layout, start) startDate, err := time.Parse(layout, start)
if err != nil { if err != nil {
m.App.Session.Put(r.Context(), "error", "Can't parse start date") m.App.Session.Put(r.Context(), "error", "Can't parse start date")
http.Redirect(w, r, "/availability", http.StatusTemporaryRedirect) http.Redirect(w, r, "/availability", http.StatusSeeOther)
return return
} }
endDate, err := time.Parse(layout, end) endDate, err := time.Parse(layout, end)
if err != nil { if err != nil {
m.App.Session.Put(r.Context(), "error", "Can't parse end date") m.App.Session.Put(r.Context(), "error", "Can't parse end date")
http.Redirect(w, r, "/availability", http.StatusTemporaryRedirect) http.Redirect(w, r, "/availability", http.StatusSeeOther)
return return
} }
rooms, err := m.DB.SearchAvailabilityForAllRooms(startDate, endDate) rooms, err := m.DB.SearchAvailabilityForAllRooms(startDate, endDate)
if err != nil { if err != nil {
m.App.Session.Put(r.Context(), "error", "Can't connect to database") m.App.Session.Put(r.Context(), "error", "Can't connect to database")
http.Redirect(w, r, "/availability", http.StatusTemporaryRedirect) http.Redirect(w, r, "/availability", http.StatusSeeOther)
return return
} }
@ -402,7 +402,7 @@ func (m *Repository) ChooseRoom(w http.ResponseWriter, r *http.Request) {
roomID, err := strconv.Atoi(exploded[2]) roomID, err := strconv.Atoi(exploded[2])
if err != nil { if err != nil {
m.App.Session.Put(r.Context(), "error", "Can't parse roomID") m.App.Session.Put(r.Context(), "error", "Can't parse roomID")
http.Redirect(w, r, "/availability", http.StatusTemporaryRedirect) http.Redirect(w, r, "/availability", http.StatusSeeOther)
return return
} }
m.App.Session.Get(r.Context(), "reservation") m.App.Session.Get(r.Context(), "reservation")
@ -410,7 +410,7 @@ func (m *Repository) ChooseRoom(w http.ResponseWriter, r *http.Request) {
res, ok := m.App.Session.Get(r.Context(), "reservation").(models.Reservation) res, ok := m.App.Session.Get(r.Context(), "reservation").(models.Reservation)
if !ok { if !ok {
m.App.Session.Put(r.Context(), "error", "Can't get reservation from session") m.App.Session.Put(r.Context(), "error", "Can't get reservation from session")
http.Redirect(w, r, "/availability", http.StatusTemporaryRedirect) http.Redirect(w, r, "/availability", http.StatusSeeOther)
return return
} }
@ -432,19 +432,19 @@ func (m *Repository) BookRoom(w http.ResponseWriter, r *http.Request) {
startDate, err := time.Parse(layout, sd) startDate, err := time.Parse(layout, sd)
if err != nil { if err != nil {
m.App.Session.Put(r.Context(), "error", "Can't parse start date") m.App.Session.Put(r.Context(), "error", "Can't parse start date")
http.Redirect(w, r, "/availability", http.StatusTemporaryRedirect) http.Redirect(w, r, "/availability", http.StatusSeeOther)
return return
} }
endDate, err := time.Parse(layout, ed) endDate, err := time.Parse(layout, ed)
if err != nil { if err != nil {
m.App.Session.Put(r.Context(), "error", "Can't parse end date") m.App.Session.Put(r.Context(), "error", "Can't parse end date")
http.Redirect(w, r, "/availability", http.StatusTemporaryRedirect) http.Redirect(w, r, "/availability", http.StatusSeeOther)
return return
} }
room, err := m.DB.GetRoomById(roomID) room, err := m.DB.GetRoomById(roomID)
if err != nil { if err != nil {
m.App.Session.Put(r.Context(), "error", "Can't parse roomId") m.App.Session.Put(r.Context(), "error", "Can't parse roomId")
http.Redirect(w, r, "/availability", http.StatusTemporaryRedirect) http.Redirect(w, r, "/availability", http.StatusSeeOther)
return return
} }
res.RoomID = roomID res.RoomID = roomID
@ -554,6 +554,12 @@ func (m *Repository) AdminShowReservation(w http.ResponseWriter, r *http.Request
stringMap := make(map[string]string) stringMap := make(map[string]string)
stringMap["src"] = src stringMap["src"] = src
year := r.URL.Query().Get("y")
month := r.URL.Query().Get("m")
stringMap["month"] = month
stringMap["year"] = year
// get reservation from the database // get reservation from the database
res, err := m.DB.GetReservationByID(id) res, err := m.DB.GetReservationByID(id)
if err != nil { if err != nil {
@ -610,8 +616,16 @@ func (m *Repository) AdminPostShowReservation(w http.ResponseWriter, r *http.Req
return return
} }
month := r.Form.Get("month")
year := r.Form.Get("year")
m.App.Session.Put(r.Context(), "flash", "Changes saved") m.App.Session.Put(r.Context(), "flash", "Changes saved")
if year == "" {
log.Println(year, month)
http.Redirect(w, r, fmt.Sprintf("/admin/reservations-%s", src), http.StatusSeeOther) http.Redirect(w, r, fmt.Sprintf("/admin/reservations-%s", src), http.StatusSeeOther)
} else {
http.Redirect(w, r, fmt.Sprintf("/admin/reservations-calendar?y=%s&m=%s", year, month), http.StatusSeeOther)
}
} }
// AdminReservationsCalendar displays the reservation calendar // AdminReservationsCalendar displays the reservation calendar
@ -685,8 +699,9 @@ func (m *Repository) AdminReservationsCalendar(w http.ResponseWriter, r *http.Re
reservationMap[d.Format("2006-01-2")] = y.ReservationID reservationMap[d.Format("2006-01-2")] = y.ReservationID
} }
} else { } else {
// it's a block // it's a block.
blockMap[y.StartDate.Format("2006-01-2")] = y.ReservationID // NOTE:A block can only be set day by day
blockMap[y.StartDate.Format("2006-01-2")] = y.ID
} }
} }
data[fmt.Sprintf("reservation_map_%d", x.ID)] = reservationMap data[fmt.Sprintf("reservation_map_%d", x.ID)] = reservationMap
@ -710,9 +725,16 @@ func (m *Repository) AdminProcessReservation(w http.ResponseWriter, r *http.Requ
_ = m.DB.UpdateProcessedForReservation(id, 1) _ = m.DB.UpdateProcessedForReservation(id, 1)
year := r.URL.Query().Get("y")
month := r.URL.Query().Get("m")
m.App.Session.Put(r.Context(), "flash", "Reservation marked as processed") m.App.Session.Put(r.Context(), "flash", "Reservation marked as processed")
if year == "" {
http.Redirect(w, r, fmt.Sprintf("/admin/reservations-%s", src), http.StatusSeeOther) http.Redirect(w, r, fmt.Sprintf("/admin/reservations-%s", src), http.StatusSeeOther)
} else {
http.Redirect(w, r, fmt.Sprintf("/admin/reservations-calendar?y=%s&m=%s", year, month), http.StatusSeeOther)
}
} }
// AdminDeleteReservation deletes a reservation // AdminDeleteReservation deletes a reservation
@ -722,7 +744,74 @@ func (m *Repository) AdminDeleteReservation(w http.ResponseWriter, r *http.Reque
_ = m.DB.DeleteReservation(id) _ = m.DB.DeleteReservation(id)
year := r.URL.Query().Get("y")
month := r.URL.Query().Get("m")
m.App.Session.Put(r.Context(), "flash", fmt.Sprintf("Reservation %d deleted", id)) m.App.Session.Put(r.Context(), "flash", fmt.Sprintf("Reservation %d deleted", id))
if year == "" {
http.Redirect(w, r, fmt.Sprintf("/admin/reservations-%s", src), http.StatusSeeOther) http.Redirect(w, r, fmt.Sprintf("/admin/reservations-%s", src), http.StatusSeeOther)
} else {
http.Redirect(w, r, fmt.Sprintf("/admin/reservations-calendar?y=%s&m=%s", year, month), http.StatusSeeOther)
}
}
// AdminPostReservationsCalendar handles post of reservation calendar
func (m *Repository) AdminPostReservationsCalendar(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
helpers.ServerError(w, err)
return
}
year, _ := strconv.Atoi(r.Form.Get("y"))
month, _ := strconv.Atoi(r.Form.Get("m"))
// process blocks
rooms, err := m.DB.AllRooms()
if err != nil {
helpers.ServerError(w, err)
return
}
form := forms.New(r.PostForm)
for _, x := range rooms {
// Get the block map from the session. Loop through entire map, if we
// have an entry in the map taht does not exist in our posted data,
// and if the restriction id > 0, then it is a block we need to remove.
curMap, _ := m.App.Session.Get(r.Context(), fmt.Sprintf("block_map_%d", x.ID)).(map[string]int)
// TODO check session get ok
for name, value := range curMap {
// ok will be false if the value is not in the map
if val, ok := curMap[name]; ok {
// only pay attention to values > 0, and that are not in the form post
// the rest are just placeholders for days without blocks
if val > 0 {
if !form.Has(fmt.Sprintf("remove_block_%d_%s", x.ID, name)) {
err := m.DB.DeleteBlockByID(value)
if err != nil {
helpers.ServerError(w, err)
return
}
}
}
}
}
}
// handle new blocks
for name := range r.PostForm {
if strings.HasPrefix(name, "add_block") {
exploded := strings.Split(name, "_")
roomID, _ := strconv.Atoi(exploded[2])
startDate, _ := time.Parse("2006-01-2", exploded[3])
// insert a new block
err := m.DB.InsertBlockForRoom(roomID, startDate)
if err != nil {
helpers.ServerError(w, err)
return
}
}
}
m.App.Session.Put(r.Context(), "flash", "Changes saved")
http.Redirect(w, r, fmt.Sprintf("/admin/reservations-calendar?y=%d&m=%d", year, month), http.StatusSeeOther)
} }

View File

@ -47,6 +47,13 @@ var theTests = []struct {
{"ms", "/majors-suite", "GET", http.StatusOK}, {"ms", "/majors-suite", "GET", http.StatusOK},
{"sa", "/availability", "GET", http.StatusOK}, {"sa", "/availability", "GET", http.StatusOK},
{"contact", "/contact", "GET", http.StatusOK}, {"contact", "/contact", "GET", http.StatusOK},
{"non-existant", "/some/link", "GET", http.StatusNotFound},
{"login", "/user/login", "GET", http.StatusOK},
{"logout", "/user/logout", "GET", http.StatusOK},
{"dashboard", "/admin/dashboard", "GET", http.StatusOK},
{"all reservations", "/admin/reservations-all", "GET", http.StatusOK},
{"new reservations", "/admin/reservations-new", "GET", http.StatusOK},
{"show reservation", "/admin/reservations/new/1/show", "GET", http.StatusOK},
} }
func TestHandlers(t *testing.T) { func TestHandlers(t *testing.T) {
@ -75,8 +82,8 @@ var makeReservationTests = []struct {
expectedStatusCode int expectedStatusCode int
}{ }{
{"ok", 1, http.StatusOK}, {"ok", 1, http.StatusOK},
{"no session", 0, http.StatusTemporaryRedirect}, {"no session", 0, http.StatusSeeOther},
{"non-existant room", 100, http.StatusTemporaryRedirect}, {"non-existant room", 100, http.StatusSeeOther},
} }
func TestRepository_MakeReservation(t *testing.T) { func TestRepository_MakeReservation(t *testing.T) {
@ -141,9 +148,9 @@ var postMakeReservationTests = []struct {
{key: "start_date", value: "2050-01-01"}, {key: "start_date", value: "2050-01-01"},
{key: "end_date", value: "2050-01-02"}, {key: "end_date", value: "2050-01-02"},
}, },
http.StatusTemporaryRedirect, http.StatusSeeOther,
}, },
{"no_post_data", []postData{}, http.StatusTemporaryRedirect}, {"no_post_data", []postData{}, http.StatusSeeOther},
{ {
"missing first name", "missing first name",
[]postData{ []postData{
@ -193,7 +200,7 @@ var postMakeReservationTests = []struct {
{key: "start_date", value: "2050-01-01"}, {key: "start_date", value: "2050-01-01"},
{key: "end_date", value: "2050-01-02"}, {key: "end_date", value: "2050-01-02"},
}, },
http.StatusTemporaryRedirect, http.StatusSeeOther,
}, },
{ {
"insert room restriction error", "insert room restriction error",
@ -206,7 +213,7 @@ var postMakeReservationTests = []struct {
{key: "start_date", value: "2050-01-01"}, {key: "start_date", value: "2050-01-01"},
{key: "end_date", value: "2050-01-02"}, {key: "end_date", value: "2050-01-02"},
}, },
http.StatusTemporaryRedirect, http.StatusSeeOther,
}, },
} }
@ -374,7 +381,7 @@ var reservationSummaryTests = []struct {
expectedStatusCode int expectedStatusCode int
}{ }{
{"ok", true, http.StatusOK}, {"ok", true, http.StatusOK},
{"nok", false, http.StatusTemporaryRedirect}, {"nok", false, http.StatusSeeOther},
} }
func Test_ReservationSummary(t *testing.T) { func Test_ReservationSummary(t *testing.T) {
@ -426,7 +433,7 @@ var postAvailabilityTests = []struct {
{"database error", []postData{ {"database error", []postData{
{key: "start", value: "2050-01-03"}, {key: "start", value: "2050-01-03"},
{key: "end", value: "2050-01-04"}, {key: "end", value: "2050-01-04"},
}, http.StatusTemporaryRedirect}, }, http.StatusSeeOther},
{"no availability", []postData{ {"no availability", []postData{
{key: "start", value: "2050-01-05"}, {key: "start", value: "2050-01-05"},
{key: "end", value: "2050-01-06"}, {key: "end", value: "2050-01-06"},
@ -434,12 +441,12 @@ var postAvailabilityTests = []struct {
{"wrong start date", []postData{ {"wrong start date", []postData{
{key: "start", value: "2050-05"}, {key: "start", value: "2050-05"},
{key: "end", value: "2050-01-06"}, {key: "end", value: "2050-01-06"},
}, http.StatusTemporaryRedirect}, }, http.StatusSeeOther},
{"wrong end date", []postData{ {"wrong end date", []postData{
{key: "start", value: "2050-01-05"}, {key: "start", value: "2050-01-05"},
{key: "end", value: "01-06"}, {key: "end", value: "01-06"},
}, http.StatusTemporaryRedirect}, }, http.StatusSeeOther},
{"wrong end date", []postData{}, http.StatusTemporaryRedirect}, {"wrong end date", []postData{}, http.StatusSeeOther},
} }
func Test_PostAvailability(t *testing.T) { func Test_PostAvailability(t *testing.T) {
@ -481,8 +488,8 @@ var chooseRoomTests = []struct {
expectedStatusCode int expectedStatusCode int
}{ }{
{"ok", "/choose-room/1", true, http.StatusSeeOther}, {"ok", "/choose-room/1", true, http.StatusSeeOther},
{"wrong room id", "/choose-room/1wrong", true, http.StatusTemporaryRedirect}, {"wrong room id", "/choose-room/1wrong", true, http.StatusSeeOther},
{"no session", "/choose-room/1", false, http.StatusTemporaryRedirect}, {"no session", "/choose-room/1", false, http.StatusSeeOther},
} }
func Test_ChooseRoom(t *testing.T) { func Test_ChooseRoom(t *testing.T) {
@ -531,17 +538,17 @@ var bookRoomTests = []struct {
{key: "id", value: "1"}, {key: "id", value: "1"},
{key: "s", value: "20-01-01"}, {key: "s", value: "20-01-01"},
{key: "e", value: "2050-01-02"}, {key: "e", value: "2050-01-02"},
}, http.StatusTemporaryRedirect}, }, http.StatusSeeOther},
{"wrong end date", []postData{ {"wrong end date", []postData{
{key: "id", value: "1"}, {key: "id", value: "1"},
{key: "s", value: "2050-01-01"}, {key: "s", value: "2050-01-01"},
{key: "e", value: "2050-0-02"}, {key: "e", value: "2050-0-02"},
}, http.StatusTemporaryRedirect}, }, http.StatusSeeOther},
{"wrong room id", []postData{ {"wrong room id", []postData{
{key: "id", value: "w"}, {key: "id", value: "w"},
{key: "s", value: "2050-01-01"}, {key: "s", value: "2050-01-01"},
{key: "e", value: "2050-01-02"}, {key: "e", value: "2050-01-02"},
}, http.StatusTemporaryRedirect}, }, http.StatusSeeOther},
} }
func Test_BookRoom(t *testing.T) { func Test_BookRoom(t *testing.T) {

View File

@ -19,7 +19,12 @@ import (
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/v5/middleware"
) )
var functions = template.FuncMap{} var functions = template.FuncMap{
"humanDate": render.HumanDate,
"formatDate": render.FormatDate,
"iterate": render.Iterate,
"add": render.Add,
}
var ( var (
app config.AppConfig app config.AppConfig
@ -28,6 +33,10 @@ var (
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
gob.Register(models.Reservation{}) gob.Register(models.Reservation{})
gob.Register(models.User{})
gob.Register(models.Room{})
gob.Register(models.Restriction{})
gob.Register(map[string]int{})
// change this to true when in production // change this to true when in production
app.InProduction = false app.InProduction = false
@ -85,6 +94,25 @@ func getRoutes() http.Handler {
mux.Post("/make-reservation", Repo.PostMakeReservation) mux.Post("/make-reservation", Repo.PostMakeReservation)
mux.Get("/reservation-summary", Repo.ReservationSummary) mux.Get("/reservation-summary", Repo.ReservationSummary)
mux.Get("/choose-room/{id}", Repo.ChooseRoom)
mux.Get("/book-room", Repo.BookRoom)
mux.Get("/user/login", Repo.ShowLogin)
mux.Post("/user/login", Repo.PostShowLogin)
mux.Get("/user/logout", Repo.Logout)
mux.Get("/admin/dashboard", Repo.AdminDashboard)
mux.Get("/admin/reservations-new", Repo.AdminNewReservations)
mux.Get("/admin/reservations-all", Repo.AdminAllReservations)
mux.Get("/admin/reservations-calendar", Repo.AdminReservationsCalendar)
mux.Post("/admin/reservations-calendar", Repo.AdminPostReservationsCalendar)
mux.Get("/admin/process-reservation/{src}/{id}/do", Repo.AdminProcessReservation)
mux.Get("/admin/delete-reservation/{src}/{id}/do", Repo.AdminDeleteReservation)
mux.Get("/admin/reservations/{src}/{id}/show", Repo.AdminShowReservation)
mux.Post("/admin/reservations/{src}/{id}", Repo.AdminPostShowReservation)
fileServer := http.FileServer(http.Dir("./static/")) fileServer := http.FileServer(http.Dir("./static/"))
mux.Handle("/static/*", http.StripPrefix("/static", fileServer)) mux.Handle("/static/*", http.StripPrefix("/static", fileServer))

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"go-udemy-web-1/internal/models" "go-udemy-web-1/internal/models"
"log"
"time" "time"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@ -459,3 +460,35 @@ func (m *postgresDBRepo) GetRestrictionsForRoomByDate(roomId int, start, end tim
} }
return restrictions, nil return restrictions, nil
} }
// InsertBlockForRoom inserts a room restriction
func (m *postgresDBRepo) InsertBlockForRoom(id int, startDate time.Time) error {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
query := `insert into room_restrictions (start_date, end_date, room_id, restriction_id,
created_at, updated_at)
values ($1, $2, $3, $4, $5, $6)`
_, err := m.DB.ExecContext(ctx, query, startDate, startDate.AddDate(0, 0, 1), id, 2, time.Now(), time.Now())
if err != nil {
log.Println(err)
return err
}
return nil
}
// DeleteBlockByID deletes a block by ID
func (m *postgresDBRepo) DeleteBlockByID(id int) error {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
query := `delete from room_restrictions where id = $1`
_, err := m.DB.ExecContext(ctx, query, id)
if err != nil {
log.Println(err)
return err
}
return nil
}

View File

@ -128,3 +128,13 @@ func (m *testDBRepo) GetRestrictionsForRoomByDate(roomId int, start, end time.Ti
var restrictions []models.RoomRestriction var restrictions []models.RoomRestriction
return restrictions, nil return restrictions, nil
} }
// InsertBlockForRoom inserts a room restriction
func (m *testDBRepo) InsertBlockForRoom(id int, startDate time.Time) error {
return nil
}
// DeleteBlockByID deletes a block by ID
func (m *testDBRepo) DeleteBlockByID(id int) error {
return nil
}

View File

@ -24,4 +24,6 @@ type DatabaseRepo interface {
UpdateProcessedForReservation(id, processed int) error UpdateProcessedForReservation(id, processed int) error
AllRooms() ([]models.Room, error) AllRooms() ([]models.Room, error)
GetRestrictionsForRoomByDate(roomId int, start, end time.Time) ([]models.RoomRestriction, error) GetRestrictionsForRoomByDate(roomId int, start, end time.Time) ([]models.RoomRestriction, error)
InsertBlockForRoom(id int, startDate time.Time) error
DeleteBlockByID(id int) error
} }

View File

@ -26,7 +26,7 @@ All Reservations
<tr> <tr>
<td>{{ .ID}}</td> <td>{{ .ID}}</td>
<td> <td>
<a href="/admin/reservations/all/{{.ID}}"> <a href="/admin/reservations/all/{{.ID}}/show">
{{ .LastName}} {{ .LastName}}
</a> </a>
</td> </td>

View File

@ -26,7 +26,7 @@ New Reservations
<tr> <tr>
<td>{{ .ID}}</td> <td>{{ .ID}}</td>
<td> <td>
<a href="/admin/reservations/new/{{.ID}}"> <a href="/admin/reservations/new/{{.ID}}/show">
{{ .LastName}} {{ .LastName}}
</a> </a>
</td> </td>

View File

@ -26,8 +26,15 @@ Reservations Calendar
</div> </div>
<div class="clearfix"></div> <div class="clearfix"></div>
{{range $rooms}} <form method="post" action="/admin/reservations-calendar">
{{$roomId := .ID}} <input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<input type="hidden" name="m" value="{{index .StringMap "this_month"}}">
<input type="hidden" name="y" value="{{index .StringMap "this_month_year"}}">
{{range $rooms}}
{{$roomID := .ID}}
{{$blocks := index $.Data (printf "block_map_%d" .ID)}}
{{$reservations := index $.Data (printf "reservation_map_%d" .ID)}}
<h4 class="mt-4">{{.RoomName}}</h4> <h4 class="mt-4">{{.RoomName}}</h4>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-bordered table-sm"> <table class="table table-bordered table-sm">
@ -41,12 +48,30 @@ Reservations Calendar
<tr class="table-light"> <tr class="table-light">
{{range $index := iterate $dim}} {{range $index := iterate $dim}}
<td class="text-center"> <td class="text-center">
<input type="checkbox" name="checked" value=""> {{if gt (index $reservations (printf "%s-%s-%d" $curYear $curMonth (add $index 1))) 0}}
<a href="/admin/reservations/cal/{{index $reservations (printf "%s-%s-%d" $curYear $curMonth (add $index 1))}}/show?y={{$curYear}}&m={{$curMonth}}">
<span class="text-danger">R</span>
</a>
{{else}}
<input
{{if gt (index $blocks (printf "%s-%s-%d" $curYear $curMonth (add $index 1))) 0}}
checked
name="remove_block_{{$roomID}}_{{printf "%s-%s-%d" $curYear $curMonth (add $index 1)}}"
value="{{index $blocks (printf "%s-%s-%d" $curYear $curMonth (add $index 1))}}"
{{else}}
name="add_block_{{$roomID}}_{{printf "%s-%s-%d" $curYear $curMonth (add $index 1)}}"
value="1"
{{end}}
type="checkbox">
{{end}}
</td> </td>
{{end}} {{end}}
</tr> </tr>
</table> </table>
</div> </div>
{{end}} {{end}}
<hr>
<input type="submit" class="btn btn-primary" value="Save Changes">
</form>
</div> </div>
{{end}} {{end}}

View File

@ -15,6 +15,8 @@ Reservation
</p> </p>
<form method="post" action="/admin/reservations/{{$src}}/{{$res.ID}}" class="" novalidate> <form method="post" action="/admin/reservations/{{$src}}/{{$res.ID}}" class="" novalidate>
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}"> <input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
<input type="hidden" name="year" value="{{index .StringMap "year"}}">
<input type="hidden" name="month" value="{{index .StringMap "month"}}">
<div class="form-group mt-5"> <div class="form-group mt-5">
<label for="first_name">First name:</label> <label for="first_name">First name:</label>
@ -50,8 +52,14 @@ Reservation
<div class="float-start"> <div class="float-start">
<input type="submit" class="btn btn-primary" value="Save"> <input type="submit" class="btn btn-primary" value="Save">
{{if eq $src "cal"}}
<a href="#" onclick="window.history.go(-1)" class="btn btn-warning">Cancel</a>
{{else}}
<a href="/admin/reservations-{{$src}}" class="btn btn-warning">Cancel</a> <a href="/admin/reservations-{{$src}}" class="btn btn-warning">Cancel</a>
{{end}}
{{ if eq $res.Processed 0}}
<a href="#" class="btn btn-info" onclick="processRes({{$res.ID}})">Mark as Processed</a> <a href="#" class="btn btn-info" onclick="processRes({{$res.ID}})">Mark as Processed</a>
{{end}}
</div> </div>
@ -74,7 +82,7 @@ function processRes(id) {
msg: 'Are you sure?', msg: 'Are you sure?',
callback: function(result) { callback: function(result) {
if (result != false) { if (result != false) {
window.location.href = "/admin/process-reservation/{{$src}}/" + id; window.location.href = "/admin/process-reservation/{{$src}}/" + id + "/do?y={{index .StringMap "year"}}&m={{index .StringMap "month"}}";
} }
} }
}) })
@ -85,7 +93,7 @@ function deleteRes(id) {
msg: 'Are you sure?', msg: 'Are you sure?',
callback: function(result) { callback: function(result) {
if (result != false) { if (result != false) {
window.location.href = "/admin/delete-reservation/{{$src}}/" + id; window.location.href = "/admin/delete-reservation/{{$src}}/" + id + "/do?y={{index .StringMap "year"}}&m={{index .StringMap "month"}}";
} }
} }
}) })