Add dispositifs
This commit is contained in:
parent
0bb915059d
commit
8aa8fc927b
4
go.mod
4
go.mod
|
@ -8,7 +8,10 @@ replace git.coopgo.io/coopgo-platform/groups-management => ../../coopgo-platform
|
||||||
|
|
||||||
replace git.coopgo.io/coopgo-platform/fleets => ../../coopgo-platform/fleets/
|
replace git.coopgo.io/coopgo-platform/fleets => ../../coopgo-platform/fleets/
|
||||||
|
|
||||||
|
replace git.coopgo.io/coopgo-platform/agenda => ../../coopgo-platform/agenda/
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.coopgo.io/coopgo-platform/agenda v0.0.0-00010101000000-000000000000
|
||||||
git.coopgo.io/coopgo-platform/fleets v0.0.0-00010101000000-000000000000
|
git.coopgo.io/coopgo-platform/fleets v0.0.0-00010101000000-000000000000
|
||||||
git.coopgo.io/coopgo-platform/groups-management v0.0.0-00010101000000-000000000000
|
git.coopgo.io/coopgo-platform/groups-management v0.0.0-00010101000000-000000000000
|
||||||
git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-00010101000000-000000000000
|
git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-00010101000000-000000000000
|
||||||
|
@ -71,6 +74,7 @@ require (
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect
|
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect
|
||||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||||
|
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614 // indirect
|
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -667,6 +667,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
|
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
|
||||||
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
|
||||||
|
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||||
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614 h1:lwJmuuJQGclcankpPJwh8rorzB0bNbVALv8phDGh8TQ=
|
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614 h1:lwJmuuJQGclcankpPJwh8rorzB0bNbVALv8phDGh8TQ=
|
||||||
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
|
@ -0,0 +1,304 @@
|
||||||
|
package application
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators"
|
||||||
|
"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
|
||||||
|
agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi"
|
||||||
|
agendastorage "git.coopgo.io/coopgo-platform/agenda/storage"
|
||||||
|
groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
|
||||||
|
"git.coopgo.io/coopgo-platform/groups-management/storage"
|
||||||
|
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"google.golang.org/protobuf/types/known/structpb"
|
||||||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EventsByStartdate []agendastorage.Event
|
||||||
|
|
||||||
|
func (e EventsByStartdate) Len() int { return len(e) }
|
||||||
|
func (e EventsByStartdate) Less(i, j int) bool { return e[i].Startdate.Before(e[j].Startdate) }
|
||||||
|
func (e EventsByStartdate) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
|
||||||
|
|
||||||
|
type EventsForm struct {
|
||||||
|
Name string `json:"name" validate:"required"`
|
||||||
|
Type string `json:"type" validate:"required"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Address any `json:"address,omitempty"`
|
||||||
|
Allday bool `json:"allday"`
|
||||||
|
Startdate *time.Time `json:"startdate"`
|
||||||
|
Enddate *time.Time `json:"enddate"`
|
||||||
|
Starttime string `json:"starttime"`
|
||||||
|
Endtime string `json:"endtime"`
|
||||||
|
MaxSubscribers int `json:"max_subscribers" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ApplicationHandler) AgendaHome(w http.ResponseWriter, r *http.Request) {
|
||||||
|
resp, err := h.services.GRPC.Agenda.GetEvents(context.TODO(), &agenda.GetEventsRequest{
|
||||||
|
Namespaces: []string{"parcoursmob_dispositifs"},
|
||||||
|
Mindate: timestamppb.New(time.Now().Add(-24 * time.Hour)),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
responses := []agendastorage.Event{}
|
||||||
|
|
||||||
|
groupids := []string{}
|
||||||
|
for _, e := range resp.Events {
|
||||||
|
groupids = append(groupids, e.Owners...)
|
||||||
|
responses = append(responses, e.ToStorageType())
|
||||||
|
// fmt.Println(e)
|
||||||
|
// fmt.Println(e.ToStorageType())
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Sort(EventsByStartdate(responses))
|
||||||
|
|
||||||
|
groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{
|
||||||
|
Groupids: groupids,
|
||||||
|
})
|
||||||
|
groups := map[string]any{}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
for _, g := range groupsresp.Groups {
|
||||||
|
groups[g.Id] = g.ToStorageType()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h.Renderer.AgendaHome(w, r, responses, groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ApplicationHandler) AgendaCreateEvent(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method == "POST" {
|
||||||
|
// Get current group
|
||||||
|
g := r.Context().Value(identification.GroupKey)
|
||||||
|
if g == nil {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
group := g.(storage.Group)
|
||||||
|
|
||||||
|
eventForm, err := parseEventsForm(r)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(eventForm)
|
||||||
|
|
||||||
|
data, _ := structpb.NewStruct(map[string]any{
|
||||||
|
"address": eventForm.Address,
|
||||||
|
})
|
||||||
|
|
||||||
|
request := &agenda.CreateEventRequest{
|
||||||
|
Event: &agenda.Event{
|
||||||
|
Namespace: "parcoursmob_dispositifs",
|
||||||
|
Owners: []string{group.ID},
|
||||||
|
Type: eventForm.Type,
|
||||||
|
Name: eventForm.Name,
|
||||||
|
Description: eventForm.Description,
|
||||||
|
Startdate: timestamppb.New(*eventForm.Startdate),
|
||||||
|
Enddate: timestamppb.New(*eventForm.Enddate),
|
||||||
|
Starttime: eventForm.Starttime,
|
||||||
|
Endtime: eventForm.Endtime,
|
||||||
|
Allday: eventForm.Allday,
|
||||||
|
MaxSubscribers: int64(eventForm.MaxSubscribers),
|
||||||
|
Data: data,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := h.services.GRPC.Agenda.CreateEvent(context.TODO(), request)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", resp.Event.Id), http.StatusFound)
|
||||||
|
|
||||||
|
}
|
||||||
|
h.Renderer.AgendaCreateEvent(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ApplicationHandler) AgendaDisplayEvent(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
eventid := vars["eventid"]
|
||||||
|
|
||||||
|
request := &agenda.GetEventRequest{
|
||||||
|
Id: eventid,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := h.services.GRPC.Agenda.GetEvent(context.TODO(), request)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
grouprequest := &groupsmanagement.GetGroupRequest{
|
||||||
|
Id: resp.Event.Owners[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
groupresp, err := h.services.GRPC.GroupsManagement.GetGroup(context.TODO(), grouprequest)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribers := map[string]any{}
|
||||||
|
|
||||||
|
subscriberresp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(
|
||||||
|
context.TODO(),
|
||||||
|
&mobilityaccounts.GetAccountsBatchRequest{
|
||||||
|
Accountids: resp.Event.Subscribers,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
for _, sub := range subscriberresp.Accounts {
|
||||||
|
subscribers[sub.Id] = sub.ToStorageType()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g := r.Context().Value(identification.GroupKey)
|
||||||
|
if g == nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
group := g.(storage.Group)
|
||||||
|
|
||||||
|
accountids := []string{}
|
||||||
|
for _, m := range group.Members {
|
||||||
|
if !contains(resp.Event.Subscribers, m) {
|
||||||
|
accountids = append(accountids, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accountresp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(
|
||||||
|
context.TODO(),
|
||||||
|
&mobilityaccounts.GetAccountsBatchRequest{
|
||||||
|
Accountids: accountids,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
accounts := []any{}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
for _, acc := range accountresp.Accounts {
|
||||||
|
accounts = append(accounts, acc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h.Renderer.AgendaDisplayEvent(w, r, resp.Event.ToStorageType(), groupresp.Group.ToStorageType(), subscribers, accounts)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ApplicationHandler) AgendaSubscribeEvent(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
eventid := vars["eventid"]
|
||||||
|
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
subscriber := r.FormValue("subscriber")
|
||||||
|
|
||||||
|
request := &agenda.SubscribeEventRequest{
|
||||||
|
Eventid: eventid,
|
||||||
|
Subscriber: subscriber,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := h.services.GRPC.Agenda.SubscribeEvent(context.TODO(), request)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", eventid), http.StatusFound)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseEventsForm(r *http.Request) (*EventsForm, error) {
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var startdate *time.Time
|
||||||
|
var enddate *time.Time
|
||||||
|
|
||||||
|
if r.PostFormValue("startdate") != "" {
|
||||||
|
d, err := time.Parse("2006-01-02", r.PostFormValue("startdate"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
startdate = &d
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.PostFormValue("enddate") != "" {
|
||||||
|
d, err := time.Parse("2006-01-02", r.PostFormValue("enddate"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
enddate = &d
|
||||||
|
}
|
||||||
|
|
||||||
|
max_subscribers, err := strconv.Atoi(r.PostFormValue("max_subscribers"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
formData := &EventsForm{
|
||||||
|
Name: r.PostFormValue("name"),
|
||||||
|
Type: r.PostFormValue("type"),
|
||||||
|
Description: r.PostFormValue("description"),
|
||||||
|
Startdate: startdate,
|
||||||
|
Enddate: enddate,
|
||||||
|
Starttime: r.PostFormValue("starttime"),
|
||||||
|
Endtime: r.PostFormValue("endtime"),
|
||||||
|
MaxSubscribers: max_subscribers,
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.PostFormValue("allday") == "true" {
|
||||||
|
formData.Allday = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.PostFormValue("address") != "" {
|
||||||
|
var a any
|
||||||
|
json.Unmarshal([]byte(r.PostFormValue("address")), &a)
|
||||||
|
|
||||||
|
formData.Address = a
|
||||||
|
}
|
||||||
|
|
||||||
|
validate := formvalidators.New()
|
||||||
|
if err := validate.Struct(formData); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return formData, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func contains(s []string, e string) bool {
|
||||||
|
for _, a := range s {
|
||||||
|
if a == e {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import (
|
||||||
formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators"
|
formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators"
|
||||||
"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
|
"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
|
||||||
profilepictures "git.coopgo.io/coopgo-apps/parcoursmob/utils/profile-pictures"
|
profilepictures "git.coopgo.io/coopgo-apps/parcoursmob/utils/profile-pictures"
|
||||||
|
fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
|
||||||
groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
|
groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
|
||||||
"git.coopgo.io/coopgo-platform/groups-management/storage"
|
"git.coopgo.io/coopgo-platform/groups-management/storage"
|
||||||
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
|
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
|
||||||
|
@ -61,7 +62,7 @@ func (h *ApplicationHandler) BeneficiaryCreate(w http.ResponseWriter, r *http.Re
|
||||||
|
|
||||||
if r.Method == "POST" {
|
if r.Method == "POST" {
|
||||||
|
|
||||||
dataMap, err := parseForm(r)
|
dataMap, err := parseBeneficiariesForm(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
@ -128,7 +129,23 @@ func (h *ApplicationHandler) BeneficiaryDisplay(w http.ResponseWriter, r *http.R
|
||||||
//TODO filter namespaces
|
//TODO filter namespaces
|
||||||
//TODO filter groups
|
//TODO filter groups
|
||||||
|
|
||||||
h.Renderer.BeneficiaryDisplay(w, r, resp.Account.ToStorageType())
|
bookingsrequest := &fleets.GetDriverBookingsRequest{
|
||||||
|
Driver: beneficiaryID,
|
||||||
|
}
|
||||||
|
bookingsresp, err := h.services.GRPC.Fleets.GetDriverBookings(context.TODO(), bookingsrequest)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bookings := []any{}
|
||||||
|
|
||||||
|
for _, b := range bookingsresp.Bookings {
|
||||||
|
bookings = append(bookings, b.ToStorageType())
|
||||||
|
}
|
||||||
|
|
||||||
|
h.Renderer.BeneficiaryDisplay(w, r, resp.Account.ToStorageType(), bookings)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Request) {
|
func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -137,7 +154,7 @@ func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Re
|
||||||
|
|
||||||
if r.Method == "POST" {
|
if r.Method == "POST" {
|
||||||
|
|
||||||
dataMap, err := parseForm(r)
|
dataMap, err := parseBeneficiariesForm(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
@ -189,56 +206,6 @@ func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Re
|
||||||
h.Renderer.BeneficiaryUpdate(w, r, resp.Account.ToStorageType())
|
h.Renderer.BeneficiaryUpdate(w, r, resp.Account.ToStorageType())
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseForm(r *http.Request) (map[string]any, error) {
|
|
||||||
if err := r.ParseForm(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var date *time.Time
|
|
||||||
|
|
||||||
if r.PostFormValue("birthdate") != "" {
|
|
||||||
d, err := time.Parse("2006-01-02", r.PostFormValue("birthdate"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
date = &d
|
|
||||||
}
|
|
||||||
|
|
||||||
formData := BeneficiariesForm{
|
|
||||||
FirstName: r.PostFormValue("first_name"),
|
|
||||||
LastName: r.PostFormValue("last_name"),
|
|
||||||
Email: r.PostFormValue("email"),
|
|
||||||
Birthdate: date,
|
|
||||||
PhoneNumber: r.PostFormValue("phone_number"),
|
|
||||||
Gender: r.PostFormValue("gender"),
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.PostFormValue("address") != "" {
|
|
||||||
var a any
|
|
||||||
json.Unmarshal([]byte(r.PostFormValue("address")), &a)
|
|
||||||
|
|
||||||
formData.Address = a
|
|
||||||
}
|
|
||||||
|
|
||||||
validate := formvalidators.New()
|
|
||||||
if err := validate.Struct(formData); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
d, err := json.Marshal(formData)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var dataMap map[string]any
|
|
||||||
err = json.Unmarshal(d, &dataMap)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return dataMap, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *ApplicationHandler) BeneficiaryPicture(w http.ResponseWriter, r *http.Request) {
|
func (h *ApplicationHandler) BeneficiaryPicture(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
beneficiaryID := vars["beneficiaryid"]
|
beneficiaryID := vars["beneficiaryid"]
|
||||||
|
@ -312,3 +279,53 @@ func (h *ApplicationHandler) beneficiaries(r *http.Request) ([]any, error) {
|
||||||
|
|
||||||
return accounts, err
|
return accounts, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseBeneficiariesForm(r *http.Request) (map[string]any, error) {
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var date *time.Time
|
||||||
|
|
||||||
|
if r.PostFormValue("birthdate") != "" {
|
||||||
|
d, err := time.Parse("2006-01-02", r.PostFormValue("birthdate"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
date = &d
|
||||||
|
}
|
||||||
|
|
||||||
|
formData := BeneficiariesForm{
|
||||||
|
FirstName: r.PostFormValue("first_name"),
|
||||||
|
LastName: r.PostFormValue("last_name"),
|
||||||
|
Email: r.PostFormValue("email"),
|
||||||
|
Birthdate: date,
|
||||||
|
PhoneNumber: r.PostFormValue("phone_number"),
|
||||||
|
Gender: r.PostFormValue("gender"),
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.PostFormValue("address") != "" {
|
||||||
|
var a any
|
||||||
|
json.Unmarshal([]byte(r.PostFormValue("address")), &a)
|
||||||
|
|
||||||
|
formData.Address = a
|
||||||
|
}
|
||||||
|
|
||||||
|
validate := formvalidators.New()
|
||||||
|
if err := validate.Struct(formData); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
d, err := json.Marshal(formData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataMap map[string]any
|
||||||
|
err = json.Unmarshal(d, &dataMap)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataMap, nil
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
|
"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
|
||||||
fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
|
fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"google.golang.org/protobuf/types/known/structpb"
|
"google.golang.org/protobuf/types/known/structpb"
|
||||||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *ApplicationHandler) VehiclesManagementOverview(w http.ResponseWriter, r *http.Request) {
|
func (h *ApplicationHandler) VehiclesManagementOverview(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -182,6 +184,57 @@ func (h ApplicationHandler) VehicleManagementBookingDisplay(w http.ResponseWrite
|
||||||
|
|
||||||
booking := resp.Booking.ToStorageType()
|
booking := resp.Booking.ToStorageType()
|
||||||
|
|
||||||
|
if r.Method == "POST" {
|
||||||
|
r.ParseForm()
|
||||||
|
|
||||||
|
newbooking := resp.Booking
|
||||||
|
|
||||||
|
startdate := r.FormValue("startdate")
|
||||||
|
if startdate != "" {
|
||||||
|
newstartdate, _ := time.Parse("2006-01-02", startdate)
|
||||||
|
newbooking.Startdate = timestamppb.New(newstartdate)
|
||||||
|
|
||||||
|
if newstartdate.Before(newbooking.Unavailablefrom.AsTime()) {
|
||||||
|
newbooking.Unavailablefrom = timestamppb.New(newstartdate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enddate := r.FormValue("enddate")
|
||||||
|
if enddate != "" {
|
||||||
|
newenddate, _ := time.Parse("2006-01-02", enddate)
|
||||||
|
newbooking.Enddate = timestamppb.New(newenddate)
|
||||||
|
|
||||||
|
if newenddate.After(newbooking.Unavailableto.AsTime()) || newenddate.Equal(newbooking.Unavailableto.AsTime()) {
|
||||||
|
newbooking.Unavailableto = timestamppb.New(newenddate.Add(24 * time.Hour))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unavailablefrom := r.FormValue("unavailablefrom")
|
||||||
|
if unavailablefrom != "" {
|
||||||
|
newunavailablefrom, _ := time.Parse("2006-01-02", unavailablefrom)
|
||||||
|
newbooking.Unavailablefrom = timestamppb.New(newunavailablefrom)
|
||||||
|
}
|
||||||
|
|
||||||
|
unavailableto := r.FormValue("unavailableto")
|
||||||
|
if unavailableto != "" {
|
||||||
|
newunavailableto, _ := time.Parse("2006-01-02", unavailableto)
|
||||||
|
newbooking.Unavailableto = timestamppb.New(newunavailableto)
|
||||||
|
}
|
||||||
|
|
||||||
|
request := &fleets.UpdateBookingRequest{
|
||||||
|
Booking: newbooking,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := h.services.GRPC.Fleets.UpdateBooking(context.TODO(), request)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
booking = newbooking.ToStorageType()
|
||||||
|
}
|
||||||
|
|
||||||
beneficiaryrequest := &mobilityaccounts.GetAccountRequest{
|
beneficiaryrequest := &mobilityaccounts.GetAccountRequest{
|
||||||
Id: booking.Driver,
|
Id: booking.Driver,
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,15 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
|
||||||
fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
|
fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
|
||||||
|
groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
|
||||||
|
"git.coopgo.io/coopgo-platform/groups-management/storage"
|
||||||
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
|
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
|
||||||
|
"github.com/coreos/go-oidc"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
"google.golang.org/protobuf/types/known/structpb"
|
||||||
"google.golang.org/protobuf/types/known/timestamppb"
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -71,6 +76,32 @@ func (h ApplicationHandler) VehiclesSearch(w http.ResponseWriter, r *http.Reques
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h ApplicationHandler) Book(w http.ResponseWriter, r *http.Request) {
|
func (h ApplicationHandler) Book(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Get Group
|
||||||
|
g := r.Context().Value(identification.GroupKey)
|
||||||
|
if g == nil {
|
||||||
|
fmt.Println("no current group")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
current_group := g.(storage.Group)
|
||||||
|
|
||||||
|
// Get current user ID
|
||||||
|
u := r.Context().Value(identification.IdtokenKey)
|
||||||
|
if u == nil {
|
||||||
|
fmt.Println("no current user")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
current_user_token := u.(*oidc.IDToken)
|
||||||
|
|
||||||
|
// Get current user claims
|
||||||
|
c := r.Context().Value(identification.ClaimsKey)
|
||||||
|
if c == nil {
|
||||||
|
fmt.Println("no current user claims")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
current_user_claims := c.(map[string]any)
|
||||||
|
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
vehicleid := vars["vehicleid"]
|
vehicleid := vars["vehicleid"]
|
||||||
|
@ -84,6 +115,25 @@ func (h ApplicationHandler) Book(w http.ResponseWriter, r *http.Request) {
|
||||||
startdate, _ := time.Parse("2006-01-02", start)
|
startdate, _ := time.Parse("2006-01-02", start)
|
||||||
enddate, _ := time.Parse("2006-01-02", end)
|
enddate, _ := time.Parse("2006-01-02", end)
|
||||||
|
|
||||||
|
data := map[string]any{
|
||||||
|
"booked_by": map[string]any{
|
||||||
|
"user": map[string]any{
|
||||||
|
"id": current_user_token.Subject,
|
||||||
|
"display_name": current_user_claims["display_name"],
|
||||||
|
},
|
||||||
|
"group": map[string]any{
|
||||||
|
"id": current_group.ID,
|
||||||
|
"name": current_group.Data["name"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
datapb, err := structpb.NewStruct(data)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
booking := &fleets.Booking{
|
booking := &fleets.Booking{
|
||||||
Id: uuid.NewString(),
|
Id: uuid.NewString(),
|
||||||
Vehicleid: vehicleid,
|
Vehicleid: vehicleid,
|
||||||
|
@ -92,13 +142,14 @@ func (h ApplicationHandler) Book(w http.ResponseWriter, r *http.Request) {
|
||||||
Enddate: timestamppb.New(enddate),
|
Enddate: timestamppb.New(enddate),
|
||||||
Unavailablefrom: timestamppb.New(startdate),
|
Unavailablefrom: timestamppb.New(startdate),
|
||||||
Unavailableto: timestamppb.New(enddate.Add(72 * time.Hour)),
|
Unavailableto: timestamppb.New(enddate.Add(72 * time.Hour)),
|
||||||
|
Data: datapb,
|
||||||
}
|
}
|
||||||
|
|
||||||
request := &fleets.CreateBookingRequest{
|
request := &fleets.CreateBookingRequest{
|
||||||
Booking: booking,
|
Booking: booking,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := h.services.GRPC.Fleets.CreateBooking(context.TODO(), request)
|
_, err = h.services.GRPC.Fleets.CreateBooking(context.TODO(), request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
@ -136,16 +187,34 @@ func (h ApplicationHandler) VehicleBookingDisplay(w http.ResponseWriter, r *http
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// grouprequest := &groupsmanagement.GetGroupRequest{
|
grouprequest := &groupsmanagement.GetGroupRequest{
|
||||||
// Id: booking.Vehicle.Administrators[0],
|
Id: booking.Vehicle.Administrators[0],
|
||||||
// }
|
}
|
||||||
|
|
||||||
// groupresp, err := h.services.GRPC.GroupsManagement.GetGroup(context.TODO(), grouprequest)
|
groupresp, err := h.services.GRPC.GroupsManagement.GetGroup(context.TODO(), grouprequest)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// fmt.Println(err)
|
fmt.Println(err)
|
||||||
// w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
|
|
||||||
h.Renderer.VehicleBookingDisplay(w, r, booking, booking.Vehicle, beneficiaryresp.Account.ToStorageType(), "")
|
h.Renderer.VehicleBookingDisplay(w, r, booking, booking.Vehicle, beneficiaryresp.Account.ToStorageType(), groupresp.Group.ToStorageType())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ApplicationHandler) VehiclesBookingsList(w http.ResponseWriter, r *http.Request) {
|
||||||
|
request := &fleets.GetBookingsRequest{}
|
||||||
|
resp, err := h.services.GRPC.Fleets.GetBookings(context.TODO(), request)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bookings := []any{}
|
||||||
|
|
||||||
|
for _, b := range resp.Bookings {
|
||||||
|
bookings = append(bookings, b.ToStorageType())
|
||||||
|
}
|
||||||
|
|
||||||
|
h.Renderer.VehicleBookingsList(w, r, bookings)
|
||||||
}
|
}
|
||||||
|
|
11
main.go
11
main.go
|
@ -54,6 +54,7 @@ func main() {
|
||||||
|
|
||||||
r.HandleFunc("/auth/groups/", authHandler.Groups)
|
r.HandleFunc("/auth/groups/", authHandler.Groups)
|
||||||
r.HandleFunc("/auth/groups/switch", authHandler.GroupSwitch)
|
r.HandleFunc("/auth/groups/switch", authHandler.GroupSwitch)
|
||||||
|
r.HandleFunc("/", redirectApp)
|
||||||
|
|
||||||
api_router := r.PathPrefix("/api").Subrouter()
|
api_router := r.PathPrefix("/api").Subrouter()
|
||||||
api_router.HandleFunc("/", apiHandler.NotFound)
|
api_router.HandleFunc("/", apiHandler.NotFound)
|
||||||
|
@ -68,7 +69,9 @@ func main() {
|
||||||
application.HandleFunc("/beneficiaries/{beneficiaryid}", applicationHandler.BeneficiaryDisplay)
|
application.HandleFunc("/beneficiaries/{beneficiaryid}", applicationHandler.BeneficiaryDisplay)
|
||||||
application.HandleFunc("/beneficiaries/{beneficiaryid}/update", applicationHandler.BeneficiaryUpdate)
|
application.HandleFunc("/beneficiaries/{beneficiaryid}/update", applicationHandler.BeneficiaryUpdate)
|
||||||
application.HandleFunc("/beneficiaries/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
|
application.HandleFunc("/beneficiaries/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
|
||||||
|
application.HandleFunc("/members/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
|
||||||
application.HandleFunc("/vehicles/", applicationHandler.VehiclesSearch)
|
application.HandleFunc("/vehicles/", applicationHandler.VehiclesSearch)
|
||||||
|
application.HandleFunc("/vehicles/bookings/", applicationHandler.VehiclesBookingsList)
|
||||||
application.HandleFunc("/vehicles/bookings/{bookingid}", applicationHandler.VehicleBookingDisplay)
|
application.HandleFunc("/vehicles/bookings/{bookingid}", applicationHandler.VehicleBookingDisplay)
|
||||||
application.HandleFunc("/vehicles/v/{vehicleid}/b/{beneficiaryid}", applicationHandler.Book)
|
application.HandleFunc("/vehicles/v/{vehicleid}/b/{beneficiaryid}", applicationHandler.Book)
|
||||||
application.HandleFunc("/vehicles-management/", applicationHandler.VehiclesManagementOverview)
|
application.HandleFunc("/vehicles-management/", applicationHandler.VehiclesManagementOverview)
|
||||||
|
@ -76,6 +79,10 @@ func main() {
|
||||||
application.HandleFunc("/vehicles-management/fleet/{vehicleid}", applicationHandler.VehiclesFleetDisplay)
|
application.HandleFunc("/vehicles-management/fleet/{vehicleid}", applicationHandler.VehiclesFleetDisplay)
|
||||||
application.HandleFunc("/vehicles-management/fleet/{vehicleid}/update", applicationHandler.VehiclesFleetUpdate)
|
application.HandleFunc("/vehicles-management/fleet/{vehicleid}/update", applicationHandler.VehiclesFleetUpdate)
|
||||||
application.HandleFunc("/vehicles-management/bookings/{bookingid}", applicationHandler.VehicleManagementBookingDisplay)
|
application.HandleFunc("/vehicles-management/bookings/{bookingid}", applicationHandler.VehicleManagementBookingDisplay)
|
||||||
|
application.HandleFunc("/agenda/", applicationHandler.AgendaHome)
|
||||||
|
application.HandleFunc("/agenda/create-event", applicationHandler.AgendaCreateEvent)
|
||||||
|
application.HandleFunc("/agenda/{eventid}", applicationHandler.AgendaDisplayEvent)
|
||||||
|
application.HandleFunc("/agenda/{eventid}/subscribe", applicationHandler.AgendaSubscribeEvent)
|
||||||
//TODO Subrouters with middlewares checking security for each module ?
|
//TODO Subrouters with middlewares checking security for each module ?
|
||||||
application.Use(idp.Middleware)
|
application.Use(idp.Middleware)
|
||||||
application.Use(idp.GroupsMiddleware)
|
application.Use(idp.GroupsMiddleware)
|
||||||
|
@ -98,3 +105,7 @@ func main() {
|
||||||
log.Fatal(srv.ListenAndServe())
|
log.Fatal(srv.ListenAndServe())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func redirectApp(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Redirect(w, r, "/app/", http.StatusFound)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package renderer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
agendastorage "git.coopgo.io/coopgo-platform/agenda/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
const agendaMenu = "events"
|
||||||
|
|
||||||
|
func (renderer *Renderer) AgendaHome(w http.ResponseWriter, r *http.Request, events []agendastorage.Event, groups map[string]any) {
|
||||||
|
files := renderer.ThemeConfig.GetStringSlice("views.agenda.list.files")
|
||||||
|
state := NewState(r, renderer.ThemeConfig, agendaMenu)
|
||||||
|
state.ViewState = map[string]any{
|
||||||
|
"events": events,
|
||||||
|
"groups": groups,
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.Render("agenda home", w, r, files, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (renderer *Renderer) AgendaCreateEvent(w http.ResponseWriter, r *http.Request) {
|
||||||
|
files := renderer.ThemeConfig.GetStringSlice("views.agenda.create_event.files")
|
||||||
|
state := NewState(r, renderer.ThemeConfig, agendaMenu)
|
||||||
|
|
||||||
|
renderer.Render("agenda create event", w, r, files, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (renderer *Renderer) AgendaDisplayEvent(w http.ResponseWriter, r *http.Request, event any, group any, subscribers map[string]any, beneficiaries any) {
|
||||||
|
files := renderer.ThemeConfig.GetStringSlice("views.agenda.display_event.files")
|
||||||
|
state := NewState(r, renderer.ThemeConfig, agendaMenu)
|
||||||
|
state.ViewState = map[string]any{
|
||||||
|
"event": event,
|
||||||
|
"group": group,
|
||||||
|
"subscribers": subscribers,
|
||||||
|
"beneficiaries": beneficiaries,
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.Render("agenda create event", w, r, files, state)
|
||||||
|
}
|
|
@ -50,10 +50,13 @@ type BeneficiariesDisplayState struct {
|
||||||
Beneficiary any
|
Beneficiary any
|
||||||
}
|
}
|
||||||
|
|
||||||
func (renderer *Renderer) BeneficiaryDisplay(w http.ResponseWriter, r *http.Request, beneficiary any) {
|
func (renderer *Renderer) BeneficiaryDisplay(w http.ResponseWriter, r *http.Request, beneficiary any, bookings []any) {
|
||||||
files := renderer.ThemeConfig.GetStringSlice("views.beneficiaries.display.files")
|
files := renderer.ThemeConfig.GetStringSlice("views.beneficiaries.display.files")
|
||||||
state := NewState(r, renderer.ThemeConfig, beneficiariesMenu)
|
state := NewState(r, renderer.ThemeConfig, beneficiariesMenu)
|
||||||
state.ViewState = beneficiary
|
state.ViewState = map[string]any{
|
||||||
|
"beneficiary": beneficiary,
|
||||||
|
"bookings": bookings,
|
||||||
|
}
|
||||||
|
|
||||||
renderer.Render("beneficiaries_display", w, r, files, state)
|
renderer.Render("beneficiaries_display", w, r, files, state)
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,8 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende
|
||||||
Display: modules["administration"].(bool),
|
Display: modules["administration"].(bool),
|
||||||
Active: menuState == administrationMenu,
|
Active: menuState == administrationMenu,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//TODO from configuration for icons at least
|
||||||
MenuItems: []MenuItem{
|
MenuItems: []MenuItem{
|
||||||
{
|
{
|
||||||
Title: "Tableau de bord",
|
Title: "Tableau de bord",
|
||||||
|
@ -155,7 +157,7 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende
|
||||||
Title: "Véhicules partagés",
|
Title: "Véhicules partagés",
|
||||||
Link: "/app/vehicles/",
|
Link: "/app/vehicles/",
|
||||||
Active: menuState == "vehicles",
|
Active: menuState == "vehicles",
|
||||||
Icon: "hero:outline/user-group",
|
Icon: "tabler-icons:car",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,11 +170,11 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if modules["events"].(bool) {
|
if modules["agenda"].(bool) {
|
||||||
ls.MenuItems = append(ls.MenuItems, MenuItem{
|
ls.MenuItems = append(ls.MenuItems, MenuItem{
|
||||||
Title: "Dispositifs",
|
Title: "Agenda dispositifs",
|
||||||
Link: "/app/events/",
|
Link: "/app/agenda/",
|
||||||
Active: menuState == "events",
|
Active: menuState == "agenda",
|
||||||
Icon: "hero:outline/calendar",
|
Icon: "hero:outline/calendar",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,3 +38,13 @@ func (renderer *Renderer) VehicleBookingDisplay(w http.ResponseWriter, r *http.R
|
||||||
|
|
||||||
renderer.Render("vehicles search", w, r, files, state)
|
renderer.Render("vehicles search", w, r, files, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (renderer *Renderer) VehicleBookingsList(w http.ResponseWriter, r *http.Request, bookings []any) {
|
||||||
|
files := renderer.ThemeConfig.GetStringSlice("views.vehicles.bookings_list.files")
|
||||||
|
state := NewState(r, renderer.ThemeConfig, vehiclesMenu)
|
||||||
|
state.ViewState = map[string]any{
|
||||||
|
"bookings": bookings,
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer.Render("vehicles search", w, r, files, state)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AgendaService struct {
|
||||||
|
agenda.AgendaClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAgendaService(dial string) (*AgendaService, error) {
|
||||||
|
conn, err := grpc.Dial(dial, grpc.WithInsecure())
|
||||||
|
|
||||||
|
client := agenda.NewAgendaClient(conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &AgendaService{
|
||||||
|
AgendaClient: client,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi"
|
||||||
fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
|
fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
|
||||||
groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
|
groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
|
||||||
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
|
mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
|
||||||
|
@ -15,6 +16,7 @@ type GRPCServices struct {
|
||||||
MobilityAccounts mobilityaccounts.MobilityAccountsClient
|
MobilityAccounts mobilityaccounts.MobilityAccountsClient
|
||||||
GroupsManagement groupsmanagement.GroupsManagementClient
|
GroupsManagement groupsmanagement.GroupsManagementClient
|
||||||
Fleets fleets.FleetsClient
|
Fleets fleets.FleetsClient
|
||||||
|
Agenda agenda.AgendaClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
|
func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
|
||||||
|
@ -22,6 +24,7 @@ func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
|
||||||
mobilityAccountsDial = cfg.GetString("services.grpc.mobilityaccounts.dial")
|
mobilityAccountsDial = cfg.GetString("services.grpc.mobilityaccounts.dial")
|
||||||
groupsManagementDial = cfg.GetString("services.grpc.groupsmanagement.dial")
|
groupsManagementDial = cfg.GetString("services.grpc.groupsmanagement.dial")
|
||||||
fleetsDial = cfg.GetString("services.grpc.fleets.dial")
|
fleetsDial = cfg.GetString("services.grpc.fleets.dial")
|
||||||
|
agendaDial = cfg.GetString("services.grpc.agenda.dial")
|
||||||
)
|
)
|
||||||
mobilityAccounts, err := NewMobilityAccountService(mobilityAccountsDial)
|
mobilityAccounts, err := NewMobilityAccountService(mobilityAccountsDial)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -38,11 +41,17 @@ func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
agendaSvc, err := NewAgendaService(agendaDial)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return &ServicesHandler{
|
return &ServicesHandler{
|
||||||
GRPC: GRPCServices{
|
GRPC: GRPCServices{
|
||||||
MobilityAccounts: mobilityAccounts,
|
MobilityAccounts: mobilityAccounts,
|
||||||
GroupsManagement: groupsManagement,
|
GroupsManagement: groupsManagement,
|
||||||
Fleets: fleetsSvc,
|
Fleets: fleetsSvc,
|
||||||
|
Agenda: agendaSvc,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,10 @@ views:
|
||||||
booking_display:
|
booking_display:
|
||||||
files:
|
files:
|
||||||
- layouts/vehicles/booking-display.html
|
- layouts/vehicles/booking-display.html
|
||||||
|
bookings_list:
|
||||||
|
files:
|
||||||
|
- layouts/vehicles_management/_partials/bookings-list.html
|
||||||
|
- layouts/vehicles/bookings-list.html
|
||||||
vehicles_management:
|
vehicles_management:
|
||||||
overview:
|
overview:
|
||||||
files:
|
files:
|
||||||
|
@ -62,6 +66,17 @@ views:
|
||||||
booking_display:
|
booking_display:
|
||||||
files:
|
files:
|
||||||
- layouts/vehicles_management/booking-display.html
|
- layouts/vehicles_management/booking-display.html
|
||||||
|
agenda:
|
||||||
|
list:
|
||||||
|
files:
|
||||||
|
- layouts/agenda/home.html
|
||||||
|
display_event:
|
||||||
|
files:
|
||||||
|
- layouts/agenda/display-event.html
|
||||||
|
create_event:
|
||||||
|
files:
|
||||||
|
- layouts/_partials/address_autocomplete.html
|
||||||
|
- layouts/agenda/create-event.html
|
||||||
administration:
|
administration:
|
||||||
home:
|
home:
|
||||||
files:
|
files:
|
||||||
|
@ -96,4 +111,4 @@ icons:
|
||||||
hero:solid/search: <svg class="%s" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd" /></svg>
|
hero:solid/search: <svg class="%s" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd" /></svg>
|
||||||
hero:solid/selector: <svg class="%s" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" /></svg>
|
hero:solid/selector: <svg class="%s" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"><path fill-rule="evenodd" d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" /></svg>
|
||||||
img:profile-picture-placeholder: <svg class="%s" fill="currentColor" viewBox="0 0 24 24"><path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" /></svg>
|
img:profile-picture-placeholder: <svg class="%s" fill="currentColor" viewBox="0 0 24 24"><path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" /></svg>
|
||||||
|
tabler-icons:car: <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-car %s" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><circle cx="7" cy="17" r="2"></circle><circle cx="17" cy="17" r="2"></circle><path d="M5 17h-2v-6l2 -5h9l4 5h1a2 2 0 0 1 2 2v4h-2m-4 0h-6m-6 -6h15m-6 0v-5"></path></svg>
|
||||||
|
|
|
@ -117,8 +117,8 @@
|
||||||
class="focus:ring-co-blue h-4 w-4 text-co-blue border-gray-300 rounded">
|
class="focus:ring-co-blue h-4 w-4 text-co-blue border-gray-300 rounded">
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 text-sm">
|
<div class="ml-3 text-sm">
|
||||||
<label for="modules.events" class="font-medium text-gray-700">Dispositifs</label>
|
<label for="modules.events" class="font-medium text-gray-700">Agenda dispositifs</label>
|
||||||
<p class="text-gray-500">Gestion des dispositifs pour les bénéficiaires (auto-écoles sociales, événements, ...)
|
<p class="text-gray-500">Agenda des dispositifs pour les bénéficiaires (sessions permis, événements, ...)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -88,8 +88,8 @@
|
||||||
class="focus:ring-co-blue h-4 w-4 text-co-blue border-gray-300 rounded">
|
class="focus:ring-co-blue h-4 w-4 text-co-blue border-gray-300 rounded">
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 text-sm">
|
<div class="ml-3 text-sm">
|
||||||
<label for="modules.events" class="font-medium text-gray-700">Dispositifs</label>
|
<label for="modules.events" class="font-medium text-gray-700">Agenda dispositifs</label>
|
||||||
<p class="text-gray-500">Gestion des dispositifs pour les bénéficiaires (auto-écoles sociales, événements, ...)
|
<p class="text-gray-500">Agenda des dispositifs pour les bénéficiaires (sessions permis, événements, ...)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,212 @@
|
||||||
|
{{ define "content" }}
|
||||||
|
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
|
||||||
|
<h1 class="text-2xl font-semibold text-gray-900">Ajouter à l'agenda</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8 mt-8"
|
||||||
|
x-data="{
|
||||||
|
fields: {
|
||||||
|
name: null,
|
||||||
|
type: null,
|
||||||
|
description: null,
|
||||||
|
allday: false,
|
||||||
|
startdate: null,
|
||||||
|
enddate: null,
|
||||||
|
starttime: null,
|
||||||
|
endtime: null,
|
||||||
|
max_subscribers: 0,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
name: ['required'],
|
||||||
|
type: ['required'],
|
||||||
|
startdate: ['required'],
|
||||||
|
enddate: ['required'],
|
||||||
|
starttime: ['optional'],
|
||||||
|
endtime: ['optional'],
|
||||||
|
description: ['optional'],
|
||||||
|
max_subscribers: ['required', 'min:0']
|
||||||
|
},
|
||||||
|
formValidation: {
|
||||||
|
valid: false,
|
||||||
|
fields: {
|
||||||
|
name: {valid: null},
|
||||||
|
type: {valid: null},
|
||||||
|
description: {valid: null},
|
||||||
|
startdate: {valid: null},
|
||||||
|
enddate: {valid: null},
|
||||||
|
starttime: {valid: null},
|
||||||
|
endtime: {valid: null},
|
||||||
|
allday: {valid: null},
|
||||||
|
max_subscribers: {valid: null},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isFormValid: true,
|
||||||
|
validate() {
|
||||||
|
this.formValidation = Iodine.assert(this.fields, this.rules)
|
||||||
|
},
|
||||||
|
validateField(field) {
|
||||||
|
this.formValidation.fields[field] = Iodine.assert(this.fields[field], this.rules[field])
|
||||||
|
},
|
||||||
|
submit(event) {
|
||||||
|
this.validate()
|
||||||
|
if(!this.formValidation.valid) {
|
||||||
|
this.isFormValid = false
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
return this.formValidation.valid
|
||||||
|
}
|
||||||
|
}">
|
||||||
|
<form class="space-y-6" method="POST" @submit="submit">
|
||||||
|
<div class="bg-white shadow px-4 py-5 sm:rounded-lg sm:p-6">
|
||||||
|
<div class="md:grid md:grid-cols-3 md:gap-6">
|
||||||
|
<div class="md:col-span-1">
|
||||||
|
<h3 class="text-lg font-medium leading-6 text-gray-900">Informations sur le dispositif</h3>
|
||||||
|
<p class="mt-1 text-sm text-gray-500">Informations générales sur le dispositif d'accompagnement à ajouter à l'agenda</p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||||
|
<div class="grid grid-cols-6 gap-6">
|
||||||
|
<div class="col-span-6 sm:col-span-3">
|
||||||
|
<label for="name" class="block text-sm font-medium text-gray-700">Nom</label>
|
||||||
|
<input type="text" name="name" id="name"
|
||||||
|
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm rounded-2xl"
|
||||||
|
x-model="fields.name" @blur="validateField('name')"
|
||||||
|
:class="formValidation.fields.name.valid == false ? 'border-co-red border-2' : 'border-gray-300'">
|
||||||
|
</div>
|
||||||
|
<div class="sm:col-span-3">
|
||||||
|
<label for="type" class="block text-sm font-medium text-gray-700">Type de dispositif</label>
|
||||||
|
<select id="type" name="type"
|
||||||
|
x-model="fields.type" @blur="validateField('type')"
|
||||||
|
class="max-w-lg mt-1 block focus:ring-co-blue focus:border-co-blue w-full shadow-sm sm:max-w-xs sm:text-sm rounded-2xl"
|
||||||
|
:class="formValidation.fields.type.valid == false ? 'border-co-red border-2' : 'border-gray-300'">
|
||||||
|
<option></option>
|
||||||
|
<option value="Permis accéléré">Permis accéléré</option>
|
||||||
|
<option value="Auto-école sociale (classique)">Auto-école sociale (classique)</option>
|
||||||
|
<option value="Information collective">Information collective</option>
|
||||||
|
<option value="Autres">Autres</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label for="description" class="block text-sm font-medium text-gray-700">Description</label>
|
||||||
|
<div class="mt-1">
|
||||||
|
<textarea rows="4" name="description" id="descrpition"
|
||||||
|
x-model="fields.description" @blur="validateField('description')"
|
||||||
|
:class="formValidation.fields.description.valid == false ? 'border-co-red border-2' : 'border-gray-300'"
|
||||||
|
class="shadow-sm focus:ring-co-blue focus:border-co-blue block w-full sm:text-sm border-gray-300 rounded-2xl"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{ $fieldName := "address" }}
|
||||||
|
{{ template "address_autocomplete" dict "FieldName" $fieldName }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white shadow px-4 py-5 sm:rounded-lg sm:p-6">
|
||||||
|
<div class="md:grid md:grid-cols-3 md:gap-6">
|
||||||
|
<div class="md:col-span-1">
|
||||||
|
<h3 class="text-lg font-medium leading-6 text-gray-900">Planification</h3>
|
||||||
|
<p class="mt-1 text-sm text-gray-500">Dates et horaires de l'événement</p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-5 space-y-6 md:mt-0 md:col-span-2 align-middle">
|
||||||
|
<div class="grid grid-cols-6 gap-6">
|
||||||
|
|
||||||
|
<div class="col-span-6">
|
||||||
|
|
||||||
|
<button type="button" class="relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-co-blue focus:ring-offset-2" role="switch" aria-checked="false"
|
||||||
|
:class="fields.allday ? 'bg-co-blue' : 'bg-gray-200'"
|
||||||
|
@click="fields.allday = ! fields.allday">
|
||||||
|
<span class="sr-only">Use setting</span>
|
||||||
|
<!-- Enabled: "translate-x-5", Not Enabled: "translate-x-0" -->
|
||||||
|
<span aria-hidden="true" class="pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
|
||||||
|
:class="fields.allday ? 'translate-x-5' : 'translate-x-0'"></span>
|
||||||
|
</button> <span class="text-md font-medium text-gray-700 ml-2">Toute la journée</span>
|
||||||
|
<input type="hidden" name="allday" x-model="fields.allday">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sm:col-span-6">
|
||||||
|
<div class="inline-flex w-full">
|
||||||
|
<div class="flex-1">
|
||||||
|
<label for="startdate" class="block text-sm font-medium text-gray-700">Date de début</label>
|
||||||
|
<input type="date" name="startdate" id="startdate" placeholder="JJ/MM/AAAA"
|
||||||
|
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm rounded-l-2xl"
|
||||||
|
x-model="fields.startdate" @blur="validateField('startdate')"
|
||||||
|
:class="formValidation.fields.startdate.valid == false ? 'border-co-red border-2' : 'border-gray-300'">
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<label for="enddate" class="block text-sm font-medium text-gray-700">Date de fin</label>
|
||||||
|
<input type="date" name="enddate" id="enddate" placeholder="JJ/MM/AAAA"
|
||||||
|
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm rounded-r-2xl"
|
||||||
|
x-model="fields.enddate" @blur="validateField('enddate')"
|
||||||
|
:class="formValidation.fields.enddate.valid == false ? 'border-co-red border-2' : 'border-gray-300'">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sm:col-span-6" x-show="!fields.allday">
|
||||||
|
<div class="inline-flex w-full">
|
||||||
|
<div class="flex-1">
|
||||||
|
<label for="startdate" class="block text-sm font-medium text-gray-700">Horaire de début</label>
|
||||||
|
<input type="time" name="starttime" id="starttime" placeholder="00:00"
|
||||||
|
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm rounded-l-2xl"
|
||||||
|
x-model="fields.starttime" @blur="validateField('starttime')"
|
||||||
|
:class="formValidation.fields.starttime.valid == false ? 'border-co-red border-2' : 'border-gray-300'">
|
||||||
|
</div>
|
||||||
|
<div class="flex-1">
|
||||||
|
<label for="endtime" class="block text-sm font-medium text-gray-700">Horaire de fin</label>
|
||||||
|
<input type="time" name="endtime" id="endtime" placeholder="00:00"
|
||||||
|
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm rounded-r-2xl"
|
||||||
|
x-model="fields.endtime" @blur="validateField('endtime')"
|
||||||
|
:class="formValidation.fields.endtime.valid == false ? 'border-co-red border-2' : 'border-gray-300'">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-white shadow px-4 py-5 sm:rounded-lg sm:p-6">
|
||||||
|
<div class="md:grid md:grid-cols-3 md:gap-6">
|
||||||
|
<div class="md:col-span-1">
|
||||||
|
<h3 class="text-lg font-medium leading-6 text-gray-900">Paramètres</h3>
|
||||||
|
<p class="mt-1 text-sm text-gray-500">Paramètres du dispositift (nombre de places disponibles, etc...)</p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-5 space-y-6 md:mt-0 md:col-span-2 align-middle">
|
||||||
|
<div class="grid grid-cols-6 gap-6">
|
||||||
|
<div class="col-span-6 sm:col-span-3">
|
||||||
|
<label for="max_subscribers" class="block text-sm font-medium text-gray-700">Places disponibles (0 = illimité)</label>
|
||||||
|
<input type="number" name="max_subscribers" id="max_subscribers"
|
||||||
|
class="mt-1 focus:ring-co-blue focus:border-co-blue block w-full shadow-sm sm:text-sm rounded-2xl"
|
||||||
|
x-model="fields.max_subscribers" @blur="validateField('max_subscribers')"
|
||||||
|
:class="formValidation.fields.max_subscribers.valid == false ? 'border-co-red border-2' : 'border-gray-300'">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="flex justify-end">
|
||||||
|
<p x-show="! isFormValid" class="px-4 py-2 text-sm text-co-red">Certains champs de sont pas valides.</p>
|
||||||
|
<a href="/app/agenda/">
|
||||||
|
<button type="button"
|
||||||
|
class="bg-white py-2 px-4 border border-gray-300 rounded-2xl shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-co-blue">Annuler</button>
|
||||||
|
</a>
|
||||||
|
<button type="submit"
|
||||||
|
class="ml-3 inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-2xl text-white bg-co-blue hover:bg-co-blue focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-co-blue">Ajouter</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{end}}
|
|
@ -0,0 +1,140 @@
|
||||||
|
{{ define "content" }}
|
||||||
|
<main class="py-10">
|
||||||
|
<div class="max-w-3xl mx-auto px-4 sm:px-6 md:flex md:items-center md:justify-between md:space-x-5 lg:max-w-7xl lg:px-8">
|
||||||
|
<div class="flex items-center space-x-5">
|
||||||
|
<div>
|
||||||
|
<h1 class="text-2xl font-bold text-gray-900">{{.ViewState.event.Name}}</h1>
|
||||||
|
<p class="text-m font-medium text-gray-500">
|
||||||
|
{{if eq .ViewState.event.Startdate .ViewState.event.Enddate}}
|
||||||
|
Le {{(timeFrom .ViewState.event.Startdate).Format "02/01/2006"}}
|
||||||
|
{{else}}
|
||||||
|
Du {{(timeFrom .ViewState.event.Startdate).Format "02/01/2006"}} au {{(timeFrom .ViewState.event.Enddate).Format "02/01/2006"}}
|
||||||
|
{{end}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-8 max-w-3xl mx-auto grid grid-cols-1 gap-6 sm:px-6 lg:max-w-7xl lg:grid-flow-col-dense lg:grid-cols-3">
|
||||||
|
<div class="space-y-6 lg:col-start-1 lg:col-span-2">
|
||||||
|
<section aria-labelledby="event-information-title">
|
||||||
|
<div class="bg-white shadow sm:rounded-lg">
|
||||||
|
<div class="px-4 py-5 sm:px-6">
|
||||||
|
<h2 id="event-information-title" class="text-lg leading-6 font-medium text-gray-900">Informations</h2>
|
||||||
|
<p class="mt-1 max-w-2xl text-sm text-gray-500">Informations sur le dispositif.</p>
|
||||||
|
</div>
|
||||||
|
<div class="border-t border-gray-200 px-4 py-5 sm:px-6">
|
||||||
|
<dl class="grid grid-cols-1 gap-x-4 gap-y-8 sm:grid-cols-2">
|
||||||
|
{{if .ViewState.event.Type}}
|
||||||
|
<div class="sm:col-span-1">
|
||||||
|
<dt class="text-sm font-medium text-gray-500">Type</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.event.Type}}</dd>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{if .ViewState.group}}
|
||||||
|
<div class="sm:col-span-1">
|
||||||
|
<dt class="text-sm font-medium text-gray-500">Structure gestionnaire</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.group.Data.name}}</dd>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{if .ViewState.event.MaxSubscribers}}
|
||||||
|
<div class="sm:col-span-1">
|
||||||
|
<dt class="text-sm font-medium text-gray-500">Total places</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.event.MaxSubscribers}}</dd>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{if ne .ViewState.event.MaxSubscribers 0}}
|
||||||
|
<div class="sm:col-span-1">
|
||||||
|
<dt class="text-sm font-medium text-gray-500">Places restantes</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.event.RemainingSubscriptions}}</dd>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{if .ViewState.event.Data.address}}
|
||||||
|
<div class="sm:col-span-1">
|
||||||
|
<dt class="text-sm font-medium text-gray-500">Adresse</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.event.Data.address.properties.label}}</dd>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{if .ViewState.event.Description}}
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<dt class="text-sm font-medium text-gray-500">Description</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.event.Description}}</dd>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<section aria-labelledby="subscribers-title" class="lg:col-start-3 lg:col-span-1">
|
||||||
|
<div class="bg-white px-4 py-5 shadow sm:rounded-lg sm:px-6">
|
||||||
|
<h2 id="subscribers-title" class="text-lg font-medium text-gray-900">Inscrire un bénéficiaire</h2>
|
||||||
|
{{if gt .ViewState.event.RemainingSubscriptions 0}}
|
||||||
|
<form class="mt-4" action="/app/agenda/{{.ViewState.event.ID}}/subscribe" method="POST">
|
||||||
|
<div class="relative mt-1 mb-4" x-data="{
|
||||||
|
text: '',
|
||||||
|
beneficiariesListOpen: false,
|
||||||
|
beneficiaries: {{json .ViewState.beneficiaries}},
|
||||||
|
filteredBeneficiaries: (text) => {
|
||||||
|
if(text=='') return beneficiaries
|
||||||
|
return this.beneficiaries.filter(b => b['data']['first_name'].includes(text) || b['data']['last_name'].includes(text))
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
beneficiaryid: {{if .ViewState.search}}'{{.ViewState.search.beneficiary.ID}}'{{else}}null{{end}},
|
||||||
|
},
|
||||||
|
selectbeneficiary(beneficiary) {
|
||||||
|
console.log(beneficiary)
|
||||||
|
this.fields.beneficiaryid = beneficiary.id
|
||||||
|
this.text = beneficiary.data.first_name + ' ' + beneficiary.data.last_name
|
||||||
|
this.beneficiariesListOpen = false
|
||||||
|
}
|
||||||
|
}">
|
||||||
|
<input @focus="beneficiariesListOpen = true" x-model="text" id="combobox" type="text" class="w-full rounded-2xl border border-gray-300 bg-white py-2 pl-3 pr-12 shadow-sm focus:border-co-blue focus:outline-none focus:ring-1 focus:ring-co-blue sm:text-sm" role="combobox" aria-controls="options" aria-expanded="false">
|
||||||
|
|
||||||
|
<button @click="beneficiariesListOpen = ! beneficiariesListOpen" type="button" class="absolute inset-y-0 right-0 flex items-center rounded-r-2xl px-2 focus:outline-none">
|
||||||
|
<!-- Heroicon name: solid/selector -->
|
||||||
|
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||||
|
<path fill-rule="evenodd" d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<ul x-show="beneficiariesListOpen" class="absolute z-10 mt-1 max-h-60 w-full overflow-auto rounded-xl bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm" id="options" role="listbox">
|
||||||
|
|
||||||
|
<template x-for="beneficiary in beneficiaries">
|
||||||
|
<li @click="selectbeneficiary(beneficiary)" class="relative cursor-default hover:bg-gray-100 select-none py-2 pl-3 pr-9 text-gray-900" id="option-0" role="option" tabindex="-1">
|
||||||
|
|
||||||
|
<span class="truncate" x-text="beneficiary.data.first_name"></span> <span class="truncate" x-text="beneficiary.data.last_name"></span>
|
||||||
|
|
||||||
|
<span class="absolute inset-y-0 right-0 flex items-center pr-4 text-co-blue">
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
<input type="hidden" name="subscriber" x-model="fields.beneficiaryid">
|
||||||
|
</div>
|
||||||
|
<button type="submit"
|
||||||
|
class="rounded-2xl border border-transparent bg-co-blue px-4 py-2 w-full text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-co-blue focus:ring-offset-2 sm:w-auto">
|
||||||
|
Inscrire le bénéficiaire
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{{else}}
|
||||||
|
<p class="p-12 text-gray-500 text-center text-md">Il n'y a plus de place disponible</p>
|
||||||
|
{{end}}
|
||||||
|
{{if .ViewState.subscribers}}
|
||||||
|
<h2 id="subscribers-title" class="text-lg font-medium text-gray-900 mt-10">Inscrits</h2>
|
||||||
|
<div class="mt-2">
|
||||||
|
{{range .ViewState.subscribers}}
|
||||||
|
<ul class="p-1">
|
||||||
|
<a href="/app/beneficiaries/{{.ID}}">
|
||||||
|
<li class="inline-flex text-sm p-2"><img class="h-6 w-6 rounded-co mr-2" src="/app/beneficiaries/{{.ID}}/picture"> {{.Data.first_name}} {{.Data.last_name}}</li>
|
||||||
|
</a>
|
||||||
|
</ul>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1,110 @@
|
||||||
|
{{define "content"}}
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
|
||||||
|
<h1 class="text-2xl font-semibold text-gray-900">Agenda dispositifs</h1>
|
||||||
|
|
||||||
|
<div class="sm:flex sm:items-center">
|
||||||
|
<div class="sm:flex-auto">
|
||||||
|
<p class="mt-2 text-sm text-gray-700"></p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
|
||||||
|
<a href="/app/agenda/create-event">
|
||||||
|
<button type="button"
|
||||||
|
class="inline-flex items-center justify-center rounded-2xl border border-transparent bg-co-blue px-4 py-2 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-ci-blue focus:ring-offset-2 sm:w-auto">
|
||||||
|
{{$.IconSet.Icon "hero:outline/plus-circle" "h-5 w-5 mr-3"}}
|
||||||
|
Ajouter un dispositif
|
||||||
|
</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
|
||||||
|
<div class="mt-8 flex flex-col">
|
||||||
|
<div class="-my-2 -mx-4 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||||
|
<div class="inline-block min-w-full py-2 align-middle md:px-6 lg:px-8">
|
||||||
|
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 md:rounded-lg">
|
||||||
|
<table class="min-w-full divide-y divide-gray-300">
|
||||||
|
<thead class="bg-gray-50">
|
||||||
|
<tr>
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Type de dispositif
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Structure
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Nom
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Lieu
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Dates
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Places disponibles
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Bénéficiaires positionnés
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6">
|
||||||
|
<span class="sr-only">Actions</span>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
<tbody class="divide-y divide-gray-200 bg-white">
|
||||||
|
{{range .ViewState.events}}
|
||||||
|
<tr>
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="text-gray-900" >{{.Type}}</div>
|
||||||
|
</td>
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
|
||||||
|
<div class="text-gray-900" >
|
||||||
|
{{range .Owners}}
|
||||||
|
{{if (index $.ViewState.groups .)}}
|
||||||
|
{{(index $.ViewState.groups .).Data.name}}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="text-gray-900" >{{.Name}}</div>
|
||||||
|
</td>
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="text-gray-900" >{{if .Data.address}}{{.Data.address.properties.label}}{{end}}</div>
|
||||||
|
</td>
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="text-gray-900" >
|
||||||
|
{{if eq .Startdate .Enddate}}
|
||||||
|
Le {{(timeFrom .Startdate).Format "02/01/2006"}}
|
||||||
|
{{else}}
|
||||||
|
Du {{(timeFrom .Startdate).Format "02/01/2006"}} <br />Au {{(timeFrom .Enddate).Format "02/01/2006"}}
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="text-gray-900" >{{.RemainingSubscriptions}}</div>
|
||||||
|
</td>
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="flex -space-x-1 overflow-hidden" >
|
||||||
|
{{range .Subscribers}}
|
||||||
|
<img class="inline-block h-6 w-6 rounded-co ring-2 ring-white" src="/app/beneficiaries/{{.}}/picture" >
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<a href="/app/agenda/{{.ID}}" class="text-co-blue hover:text-co-blue">Voir</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
|
@ -1,8 +1,16 @@
|
||||||
{{define "beneficiary_vehicles"}}
|
{{define "beneficiary_vehicles"}}
|
||||||
<div class="px-4 py-6 sm:px-6">
|
<div class="px-4 py-6 sm:px-6">
|
||||||
|
{{if .ViewState.bookings}}
|
||||||
|
<h3 class="text-lg">Mises à disposition réalisées</h3>
|
||||||
|
<ul class="my-8">
|
||||||
|
{{range .ViewState.bookings}}
|
||||||
|
<li class="text-sm">Du {{(timeFrom .Startdate).Format "02/01/2006"}} au {{(timeFrom .Enddate).Format "02/01/2006"}}</li>
|
||||||
|
{{end}}
|
||||||
|
</ul>
|
||||||
|
{{end}}
|
||||||
<h3 class="text-lg">Réserver un véhicule</h3>
|
<h3 class="text-lg">Réserver un véhicule</h3>
|
||||||
<form method="GET" action="/app/vehicles/">
|
<form method="GET" action="/app/vehicles/">
|
||||||
<input type="hidden" name="beneficiaryid" value="{{.ViewState.ID}}">
|
<input type="hidden" name="beneficiaryid" value="{{.ViewState.beneficiary.ID}}">
|
||||||
<div class="py-4 grid grid-cols-2">
|
<div class="py-4 grid grid-cols-2">
|
||||||
<div class="lg:col-span-1">
|
<div class="lg:col-span-1">
|
||||||
<label for="startdate" class="block text-sm font-medium text-gray-700">Du</label>
|
<label for="startdate" class="block text-sm font-medium text-gray-700">Du</label>
|
||||||
|
|
|
@ -5,24 +5,24 @@
|
||||||
<div class="flex items-center space-x-5">
|
<div class="flex items-center space-x-5">
|
||||||
<div class="flex-shrink-0">
|
<div class="flex-shrink-0">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<img class="h-16 w-16 rounded-co" src="/app/beneficiaries/{{.ViewState.ID}}/picture" alt="">
|
<img class="h-16 w-16 rounded-co" src="/app/beneficiaries/{{.ViewState.beneficiary.ID}}/picture" alt="">
|
||||||
<span class="absolute inset-0 shadow-inner rounded-full" aria-hidden="true"></span>
|
<span class="absolute inset-0 shadow-inner rounded-full" aria-hidden="true"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h1 class="text-2xl font-bold text-gray-900">{{.ViewState.Data.first_name}}
|
<h1 class="text-2xl font-bold text-gray-900">{{.ViewState.beneficiary.Data.first_name}}
|
||||||
{{.ViewState.Data.last_name}}</h1>
|
{{.ViewState.beneficiary.Data.last_name}}</h1>
|
||||||
<p class="text-sm font-medium text-gray-500">{{if .ViewState.Metadata.created}}Ajouté le <time
|
<p class="text-sm font-medium text-gray-500">{{if .ViewState.beneficiary.Metadata.created}}Ajouté le <time
|
||||||
datetime="2022-07-25">{{.ViewState.Metadata.created}}</time> par
|
datetime="2022-07-25">{{.ViewState.beneficiary.Metadata.created}}</time> par
|
||||||
<a href="#" class="text-gray-900">Conseiller 1</a>{{end}}
|
<a href="#" class="text-gray-900">Conseiller 1</a>{{end}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="mt-6 flex flex-col-reverse justify-stretch space-y-4 space-y-reverse sm:flex-row-reverse sm:justify-end sm:space-x-reverse sm:space-y-0 sm:space-x-3 md:mt-0 md:flex-row md:space-x-3">
|
class="mt-6 flex flex-col-reverse justify-stretch space-y-4 space-y-reverse sm:flex-row-reverse sm:justify-end sm:space-x-reverse sm:space-y-0 sm:space-x-3 md:mt-0 md:flex-row md:space-x-3">
|
||||||
<button type="button"
|
<!-- <button type="button"
|
||||||
class="inline-flex items-center justify-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-2xl text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-co-blue">Supprimer</button>
|
class="inline-flex items-center justify-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-2xl text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-co-blue">Supprimer</button> -->
|
||||||
<a href="/app/beneficiaries/{{.ViewState.ID}}/update" class="inline-flex"><button type="button"
|
<a href="/app/beneficiaries/{{.ViewState.beneficiary.ID}}/update" class="inline-flex"><button type="button"
|
||||||
class="w-full px-4 py-2 border border-transparent text-sm font-medium rounded-2xl shadow-sm text-white bg-co-blue hover:bg-co-blue focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-co-blue">Modifier</button></a>
|
class="w-full px-4 py-2 border border-transparent text-sm font-medium rounded-2xl shadow-sm text-white bg-co-blue hover:bg-co-blue focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-co-blue">Modifier</button></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -38,44 +38,44 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t border-gray-200 px-4 py-5 sm:px-6">
|
<div class="border-t border-gray-200 px-4 py-5 sm:px-6">
|
||||||
<dl class="grid grid-cols-1 gap-x-4 gap-y-8 sm:grid-cols-2">
|
<dl class="grid grid-cols-1 gap-x-4 gap-y-8 sm:grid-cols-2">
|
||||||
{{if .ViewState.Data.email}}
|
{{if .ViewState.beneficiary.Data.email}}
|
||||||
<div class="sm:col-span-1">
|
<div class="sm:col-span-1">
|
||||||
<dt class="text-sm font-medium text-gray-500">Email</dt>
|
<dt class="text-sm font-medium text-gray-500">Email</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.Data.email}}</dd>
|
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.beneficiary.Data.email}}</dd>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .ViewState.Data.phone_number}}
|
{{if .ViewState.beneficiary.Data.phone_number}}
|
||||||
<div class="sm:col-span-1">
|
<div class="sm:col-span-1">
|
||||||
<dt class="text-sm font-medium text-gray-500">Téléphone</dt>
|
<dt class="text-sm font-medium text-gray-500">Téléphone</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.Data.phone_number}}</dd>
|
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.beneficiary.Data.phone_number}}</dd>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .ViewState.Data.birthdate}}
|
{{if .ViewState.beneficiary.Data.birthdate}}
|
||||||
<div class="sm:col-span-1">
|
<div class="sm:col-span-1">
|
||||||
<dt class="text-sm font-medium text-gray-500">Date de naissance</dt>
|
<dt class="text-sm font-medium text-gray-500">Date de naissance</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900">{{(timeFrom .ViewState.Data.birthdate).Format
|
<dd class="mt-1 text-sm text-gray-900">{{(timeFrom .ViewState.beneficiary.Data.birthdate).Format
|
||||||
"02/01/2006"}}</dd>
|
"02/01/2006"}}</dd>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if and .ViewState.Data.gender (ne .ViewState.Data.gender "0")}}
|
{{if and .ViewState.beneficiary.Data.gender (ne .ViewState.beneficiary.Data.gender "0")}}
|
||||||
<div class="sm:col-span-1">
|
<div class="sm:col-span-1">
|
||||||
<dt class="text-sm font-medium text-gray-500">Genre</dt>
|
<dt class="text-sm font-medium text-gray-500">Genre</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900">{{genderISO5218 .ViewState.Data.gender}}</dd>
|
<dd class="mt-1 text-sm text-gray-900">{{genderISO5218 .ViewState.beneficiary.Data.gender}}</dd>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .ViewState.Data.address}}
|
{{if .ViewState.beneficiary.Data.address}}
|
||||||
<div class="sm:col-span-1">
|
<div class="sm:col-span-1">
|
||||||
<dt class="text-sm font-medium text-gray-500">Adresse</dt>
|
<dt class="text-sm font-medium text-gray-500">Adresse</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.Data.address.properties.label}}</dd>
|
<dd class="mt-1 text-sm text-gray-900">{{.ViewState.beneficiary.Data.address.properties.label}}</dd>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section aria-labelledby="functionalities-title" x-data="{
|
<section aria-labelledby="functionalities-title" x-data="{
|
||||||
tab: 'notes',
|
tab: 'vehicles',
|
||||||
to(event) {
|
to(event) {
|
||||||
this.tab = event.target.value
|
this.tab = event.target.value
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
<label for="tabs" class="sr-only">Select a tab</label>
|
<label for="tabs" class="sr-only">Select a tab</label>
|
||||||
<select id="tabs" name="tabs" @change="to"
|
<select id="tabs" name="tabs" @change="to"
|
||||||
class="block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md">
|
class="block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md">
|
||||||
<option value="notes">Notes</option>
|
<!-- <option value="notes">Notes</option> -->
|
||||||
|
|
||||||
<option value="journeys">Déplacements</option>
|
<option value="journeys">Déplacements</option>
|
||||||
|
|
||||||
|
@ -100,10 +100,10 @@
|
||||||
<div class="border-b border-gray-200 pl-4">
|
<div class="border-b border-gray-200 pl-4">
|
||||||
<nav class="-mb-px flex space-x-8" aria-label="Tabs">
|
<nav class="-mb-px flex space-x-8" aria-label="Tabs">
|
||||||
<!-- Current: "border-indigo-500 text-indigo-600", Default: "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" -->
|
<!-- Current: "border-indigo-500 text-indigo-600", Default: "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300" -->
|
||||||
<a href="#" @click="tab = 'notes'"
|
<!-- <a href="#" @click="tab = 'notes'"
|
||||||
class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
|
class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
|
||||||
:class="tab == 'notes' ? 'border-co-blue text-co-blue' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'">
|
:class="tab == 'notes' ? 'border-co-blue text-co-blue' : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'">
|
||||||
Notes </a>
|
Notes </a> -->
|
||||||
|
|
||||||
<a href="#" @click="tab = 'journeys'"
|
<a href="#" @click="tab = 'journeys'"
|
||||||
class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
|
class="whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
|
||||||
|
@ -129,11 +129,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div x-show="tab == 'notes'">{{template "beneficiary_notes" .}}</div>
|
|
||||||
<div x-show="tab == 'journeys'">{{template "beneficiary_journeys" .}}</div>
|
<div x-show="tab == 'journeys'">{{template "beneficiary_journeys" .}}</div>
|
||||||
<div x-show="tab == 'vehicles'">{{template "beneficiary_vehicles" .}}</div>
|
<div x-show="tab == 'vehicles'">{{template "beneficiary_vehicles" .}}</div>
|
||||||
<div x-show="tab == 'events'">{{template "beneficiary_events" .}}</div>
|
<div x-show="tab == 'events'">{{template "beneficiary_events" .}}</div>
|
||||||
<div x-show="tab == 'files'">{{template "beneficiary_files" .}}</div>
|
<div x-show="tab == 'files'">{{template "beneficiary_files" .}}</div>
|
||||||
|
<div x-show="tab == 'notes'">{{template "beneficiary_notes" .}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -92,9 +92,24 @@
|
||||||
<div class="sm:pb-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
<div class="sm:pb-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium text-gray-500">Gestionnaire</dt>
|
<dt class="text-sm font-medium text-gray-500">Gestionnaire</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
COOPGO
|
{{.ViewState.group.Data.name}}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
{{if .ViewState.booking.Data.booked_by}}
|
||||||
|
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
|
<!-- <div class="sm:pb-5 sm:grid sm:grid-cols-3 sm:gap-4"> -->
|
||||||
|
<dt class="text-sm font-medium text-gray-500">Réservé par</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
|
{{if .ViewState.booking.Data.booked_by.user}}
|
||||||
|
<a href="/app/members/{{.ViewState.booking.Data.booked_by.user.id}}" class="flex inline">
|
||||||
|
<img class="h-5 w-5 rounded-co mr-1"
|
||||||
|
src="/app/members/{{.ViewState.booking.Data.booked_by.user.id}}/picture" alt="">
|
||||||
|
{{.ViewState.booking.Data.booked_by.user.display_name}}
|
||||||
|
</a>
|
||||||
|
{{end}}
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium text-gray-500">Véhicule</dt>
|
<dt class="text-sm font-medium text-gray-500">Véhicule</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
|
@ -122,7 +137,7 @@
|
||||||
"02/01/2006"}}</dd>
|
"02/01/2006"}}</dd>
|
||||||
</div>
|
</div>
|
||||||
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium text-gray-500">Date de fin</dt>
|
<dt class="text-sm font-medium text-gray-500">Date de retour</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{(timeFrom .ViewState.booking.Enddate).Format
|
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{(timeFrom .ViewState.booking.Enddate).Format
|
||||||
"02/01/2006"}}</dd>
|
"02/01/2006"}}</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
{{define "content"}}
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
|
||||||
|
<h1 class="text-2xl font-semibold text-gray-900">Réservations</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
|
||||||
|
<div class="mt-8 flex flex-col">
|
||||||
|
<div class="-my-2 -mx-4 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||||
|
<div class="inline-block min-w-full py-2 align-middle md:px-6 lg:px-8">
|
||||||
|
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 md:rounded-lg">
|
||||||
|
<table class="min-w-full divide-y divide-gray-300">
|
||||||
|
<thead class="bg-gray-50">
|
||||||
|
<tr>
|
||||||
|
<!-- <th scope="col"
|
||||||
|
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Statut
|
||||||
|
</th> -->
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Type
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Beneficiaire
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
|
Dates
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6">
|
||||||
|
<span class="sr-only">Actions</span>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="divide-y divide-gray-200 bg-white">
|
||||||
|
|
||||||
|
{{range .ViewState.bookings}}
|
||||||
|
<tr>
|
||||||
|
<!-- <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="text-gray-900" >aa</div>
|
||||||
|
</td> -->
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="text-gray-900" >Voiture</div>
|
||||||
|
</td>
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="text-gray-900" ><img class="h-6 w-6 rounded-co"
|
||||||
|
src="/app/beneficiaries/{{.Driver}}/picture" alt=""></div>
|
||||||
|
</td>
|
||||||
|
<!-- <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="text-gray-900" >aa</div>
|
||||||
|
</td> -->
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<div class="text-gray-900" >Du {{(timeFrom .Startdate).Format "02/01/2006"}} au {{(timeFrom .Enddate).Format "02/01/2006"}}</div>
|
||||||
|
</td>
|
||||||
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
|
<a href="/app/vehicles/bookings/{{.ID}}"
|
||||||
|
class="text-co-blue hover:text-co-blue">Voir</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{end}}
|
|
@ -7,7 +7,7 @@
|
||||||
<p class="mt-2 text-sm text-gray-700"></p>
|
<p class="mt-2 text-sm text-gray-700"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
|
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
|
||||||
<a href="/app/vehicles-management/fleet/add">
|
<a href="/app/vehicles/bookings/">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="inline-flex items-center justify-center rounded-2xl border border-transparent bg-co-blue px-4 py-2 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-co-blue focus:ring-offset-2 sm:w-auto">
|
class="inline-flex items-center justify-center rounded-2xl border border-transparent bg-co-blue px-4 py-2 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-co-blue focus:ring-offset-2 sm:w-auto">
|
||||||
Voir les prêts de véhicules
|
Voir les prêts de véhicules
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
return this.beneficiaries.filter(b => b['data']['first_name'].includes(text) || b['data']['last_name'].includes(text))
|
return this.beneficiaries.filter(b => b['data']['first_name'].includes(text) || b['data']['last_name'].includes(text))
|
||||||
},
|
},
|
||||||
fields: {
|
fields: {
|
||||||
beneficiaryid: null,
|
beneficiaryid: {{if .ViewState.search}}'{{.ViewState.search.beneficiary.ID}}'{{else}}null{{end}},
|
||||||
},
|
},
|
||||||
selectbeneficiary(beneficiary) {
|
selectbeneficiary(beneficiary) {
|
||||||
console.log(beneficiary)
|
console.log(beneficiary)
|
||||||
|
|
|
@ -46,7 +46,8 @@
|
||||||
<div class="text-gray-900" >{{$vehicle.Data.licence_plate}}</div>
|
<div class="text-gray-900" >{{$vehicle.Data.licence_plate}}</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
<div class="text-gray-900" ></div>
|
<div class="text-gray-900" ><img class="h-6 w-6 rounded-co"
|
||||||
|
src="/app/beneficiaries/{{.Driver}}/picture" alt=""></div>
|
||||||
</td>
|
</td>
|
||||||
<!-- <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
<!-- <td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm sm:pl-6">
|
||||||
<div class="text-gray-900" >aa</div>
|
<div class="text-gray-900" >aa</div>
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
<p class="mt-2 text-sm text-gray-700"></p>
|
<p class="mt-2 text-sm text-gray-700"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
|
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
|
||||||
|
<button type="button"
|
||||||
|
class="inline-flex items-center justify-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-2xl text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-co-blue">
|
||||||
|
Changer de véhicule
|
||||||
|
</button>
|
||||||
<a href="/app/vehicles-management/bookings/{{.ViewState.booking.ID}}/delete">
|
<a href="/app/vehicles-management/bookings/{{.ViewState.booking.ID}}/delete">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="inline-flex items-center justify-center rounded-2xl border border-transparent bg-co-red px-4 py-2 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-co-red focus:ring-offset-2 sm:w-auto">
|
class="inline-flex items-center justify-center rounded-2xl border border-transparent bg-co-red px-4 py-2 text-sm font-medium text-white shadow-sm focus:outline-none focus:ring-2 focus:ring-co-red focus:ring-offset-2 sm:w-auto">
|
||||||
|
@ -58,7 +62,8 @@
|
||||||
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium text-gray-500">Adresse</dt>
|
<dt class="text-sm font-medium text-gray-500">Adresse</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
{{.ViewState.Data.address.properties.label}}</dd>
|
{{.ViewState.Data.address.properties.label}}
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</dl>
|
</dl>
|
||||||
|
@ -89,12 +94,28 @@
|
||||||
<div>
|
<div>
|
||||||
<div class="mt-5 border-gray-200">
|
<div class="mt-5 border-gray-200">
|
||||||
<dl class="sm:divide-y sm:divide-gray-200">
|
<dl class="sm:divide-y sm:divide-gray-200">
|
||||||
<div class="sm:pb-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
<!-- <div class="sm:pb-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium text-gray-500">Gestionnaire</dt>
|
<dt class="text-sm font-medium text-gray-500">Gestionnaire</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
COOPGO
|
COOPGO
|
||||||
</dd>
|
</dd>
|
||||||
|
</div> -->
|
||||||
|
{{if .ViewState.booking.Data.booked_by}}
|
||||||
|
<!-- <div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4"> -->
|
||||||
|
<div class="sm:pb-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
|
<dt class="text-sm font-medium text-gray-500">Prescripteur</dt>
|
||||||
|
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
|
{{if .ViewState.booking.Data.booked_by.user}}
|
||||||
|
<a href="/app/members/{{.ViewState.booking.Data.booked_by.user.id}}" class="flex inline">
|
||||||
|
<img class="h-5 w-5 rounded-co mr-1"
|
||||||
|
src="/app/members/{{.ViewState.booking.Data.booked_by.user.id}}/picture" alt="">
|
||||||
|
{{.ViewState.booking.Data.booked_by.user.display_name}}
|
||||||
|
</a>
|
||||||
|
{{end}}
|
||||||
|
{{if .ViewState.booking.Data.booked_by.group}}{{.ViewState.booking.Data.booked_by.group.name}}{{end}}
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium text-gray-500">Véhicule</dt>
|
<dt class="text-sm font-medium text-gray-500">Véhicule</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">
|
||||||
|
@ -118,23 +139,82 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium text-gray-500">Date de récupération</dt>
|
<dt class="text-sm font-medium text-gray-500">Date de récupération</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{(timeFrom .ViewState.booking.Startdate).Format
|
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2 inline-flex"
|
||||||
"02/01/2006"}}</dd>
|
x-data="{ updateOpen: false }">
|
||||||
|
<div class="w-full inline-flex" x-show="!updateOpen">
|
||||||
|
<div class="flex-1">{{(timeFrom .ViewState.booking.Startdate).Format "02/01/2006"}}</div>
|
||||||
|
<a href="#" class="text-co-blue hover:text-co-blue ml-5" @click="updateOpen = ! updateOpen">Modifier</a>
|
||||||
|
</div>
|
||||||
|
<form method="POST" class="inline-flex" x-show="updateOpen">
|
||||||
|
<div class="flex-1">
|
||||||
|
<input type="date" name="startdate" value="{{(timeFrom .ViewState.booking.Startdate).Format "2006-01-02"}}"
|
||||||
|
class="shadow-sm focus:ring-co-blue focus:border-co-blue block sm:text-sm border-gray-300 rounded-2xl">
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class=" justify-center text-co-blue px-4">
|
||||||
|
OK
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium text-gray-500">Date de fin</dt>
|
<dt class="text-sm font-medium text-gray-500">Date de retour</dt>
|
||||||
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2">{{(timeFrom .ViewState.booking.Enddate).Format
|
<dd class="mt-1 text-sm text-gray-900 sm:mt-0 sm:col-span-2"
|
||||||
"02/01/2006"}}</dd>
|
x-data="{ updateOpen: false }">
|
||||||
|
<div class="w-full inline-flex" x-show="!updateOpen">
|
||||||
|
<div class="flex-1">{{(timeFrom .ViewState.booking.Enddate).Format "02/01/2006"}}</div>
|
||||||
|
<a href="#" class="text-co-blue hover:text-co-blue ml-5" @click="updateOpen = ! updateOpen">Modifier</a>
|
||||||
|
</div>
|
||||||
|
<form method="POST" class="inline-flex" x-show="updateOpen">
|
||||||
|
<div class="flex-1">
|
||||||
|
<input type="date" name="enddate" value="{{(timeFrom .ViewState.booking.Enddate).Format "2006-01-02"}}"
|
||||||
|
class="shadow-sm focus:ring-co-blue focus:border-co-blue block sm:text-sm border-gray-300 rounded-2xl">
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class=" justify-center text-co-blue px-4">
|
||||||
|
OK
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium text-gray-500">Indisponible à partir du</dt>
|
<dt class="text-sm font-medium text-gray-500">Indisponible à partir du</dt>
|
||||||
<dd class="mt-1 text-sm font-bold text-co-red sm:mt-0 sm:col-span-2">{{(timeFrom .ViewState.booking.Unavailablefrom).Format
|
<dd class="mt-1 text-sm font-bold text-co-red sm:mt-0 sm:col-span-2 inline-flex"
|
||||||
"02/01/2006"}}</dd>
|
x-data="{ updateOpen: false }">
|
||||||
|
<div class="w-full inline-flex" x-show="!updateOpen">
|
||||||
|
<div class="flex-1">{{(timeFrom .ViewState.booking.Unavailablefrom).Format "02/01/2006"}}</div>
|
||||||
|
<a href="#" class="text-co-blue hover:text-co-blue ml-5" @click="updateOpen = ! updateOpen">Modifier</a>
|
||||||
|
</div>
|
||||||
|
<form method="POST" class="inline-flex" x-show="updateOpen">
|
||||||
|
<div class="flex-1">
|
||||||
|
<input type="date" name="unavailablefrom" value="{{(timeFrom .ViewState.booking.Unavailablefrom).Format "2006-01-02"}}"
|
||||||
|
class="shadow-sm focus:ring-co-blue focus:border-co-blue block sm:text-sm border-gray-300 rounded-2xl">
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class=" justify-center text-co-blue px-4">
|
||||||
|
OK
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
<div class="py-4 sm:py-5 sm:grid sm:grid-cols-3 sm:gap-4">
|
||||||
<dt class="text-sm font-medium text-gray-500">Sera à nouveau disponible le</dt>
|
<dt class="text-sm font-medium text-gray-500">Sera à nouveau disponible le</dt>
|
||||||
<dd class="mt-1 text-sm font-bold text-co-green sm:mt-0 sm:col-span-2">{{(timeFrom .ViewState.booking.Unavailableto).Format
|
<dd class="mt-1 text-sm font-bold text-co-green sm:mt-0 sm:col-span-2 inline-flex"
|
||||||
"02/01/2006"}}</dd>
|
x-data="{ updateOpen: false }">
|
||||||
|
<div class="w-full inline-flex" x-show="!updateOpen">
|
||||||
|
<div class="flex-1">{{(timeFrom .ViewState.booking.Unavailableto).Format "02/01/2006"}}</div>
|
||||||
|
<a href="#" class="text-co-blue hover:text-co-blue ml-5" @click="updateOpen = ! updateOpen">Modifier</a>
|
||||||
|
</div>
|
||||||
|
<form method="POST" class="inline-flex" x-show="updateOpen">
|
||||||
|
<div class="flex-1">
|
||||||
|
<input type="date" name="unavailableto" value="{{(timeFrom .ViewState.booking.Unavailableto).Format "2006-01-02"}}"
|
||||||
|
class="shadow-sm focus:ring-co-blue focus:border-co-blue block sm:text-sm border-gray-300 rounded-2xl">
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
class=" justify-center text-co-blue px-4">
|
||||||
|
OK
|
||||||
|
</button>
|
||||||
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
{{range .ViewState.vehicle.Bookings}}
|
{{range .ViewState.vehicle.Bookings}}
|
||||||
<li class="py-4 flex">
|
<li class="py-4 flex">
|
||||||
<div class="ml-3">
|
<div class="ml-3">
|
||||||
<a href="/vehicles/bookings/{{.ID}}" class="hover:bg-gray-200">
|
<a href="/app/vehicles-management/bookings/{{.ID}}" class="hover:bg-gray-200">
|
||||||
<p class="text-sm font-medium text-gray-900">Du {{(timeFrom .Startdate).Format "02/01/2006"}} au {{(timeFrom .Enddate).Format "02/01/2006"}}</p>
|
<p class="text-sm font-medium text-gray-900">Du {{(timeFrom .Startdate).Format "02/01/2006"}} au {{(timeFrom .Enddate).Format "02/01/2006"}}</p>
|
||||||
<p class="text-sm text-gray-500"></p>
|
<p class="text-sm text-gray-500"></p>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -798,14 +798,6 @@ html {
|
||||||
left: 0px;
|
left: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-4 {
|
|
||||||
top: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.left-4 {
|
|
||||||
left: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.z-40 {
|
.z-40 {
|
||||||
z-index: 40;
|
z-index: 40;
|
||||||
}
|
}
|
||||||
|
@ -830,22 +822,10 @@ html {
|
||||||
grid-column: span 3 / span 3;
|
grid-column: span 3 / span 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.col-span-2 {
|
|
||||||
grid-column: span 2 / span 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.col-span-4 {
|
|
||||||
grid-column: span 4 / span 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.col-span-5 {
|
.col-span-5 {
|
||||||
grid-column: span 5 / span 5;
|
grid-column: span 5 / span 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.m-auto {
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx-auto {
|
.mx-auto {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
@ -861,6 +841,11 @@ html {
|
||||||
margin-right: -1rem;
|
margin-right: -1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.my-4 {
|
||||||
|
margin-top: 1rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.-my-1\.5 {
|
.-my-1\.5 {
|
||||||
margin-top: -0.375rem;
|
margin-top: -0.375rem;
|
||||||
margin-bottom: -0.375rem;
|
margin-bottom: -0.375rem;
|
||||||
|
@ -871,9 +856,9 @@ html {
|
||||||
margin-bottom: -0.25rem;
|
margin-bottom: -0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-4 {
|
.my-8 {
|
||||||
margin-top: 1rem;
|
margin-top: 2rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.-mr-12 {
|
.-mr-12 {
|
||||||
|
@ -952,18 +937,18 @@ html {
|
||||||
margin-bottom: -1px;
|
margin-bottom: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.-mb-8 {
|
|
||||||
margin-bottom: -2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.-ml-px {
|
|
||||||
margin-left: -1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.-ml-4 {
|
.-ml-4 {
|
||||||
margin-left: -1rem;
|
margin-left: -1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.-mt-4 {
|
||||||
|
margin-top: -1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb-4 {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.-mt-2 {
|
.-mt-2 {
|
||||||
margin-top: -0.5rem;
|
margin-top: -0.5rem;
|
||||||
}
|
}
|
||||||
|
@ -980,12 +965,20 @@ html {
|
||||||
margin-right: -0.25rem;
|
margin-right: -0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mb-4 {
|
.mr-2 {
|
||||||
margin-bottom: 1rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.-mt-4 {
|
.mr-0 {
|
||||||
margin-top: -1rem;
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-16 {
|
||||||
|
margin-top: 4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-12 {
|
||||||
|
margin-top: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
|
@ -1012,10 +1005,6 @@ html {
|
||||||
display: table;
|
display: table;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flow-root {
|
|
||||||
display: flow-root;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid {
|
.grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
}
|
}
|
||||||
|
@ -1060,10 +1049,6 @@ html {
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h-96 {
|
|
||||||
height: 24rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.max-h-60 {
|
.max-h-60 {
|
||||||
max-height: 15rem;
|
max-height: 15rem;
|
||||||
}
|
}
|
||||||
|
@ -1116,12 +1101,8 @@ html {
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.w-0\.5 {
|
.w-11 {
|
||||||
width: 0.125rem;
|
width: 2.75rem;
|
||||||
}
|
|
||||||
|
|
||||||
.w-0 {
|
|
||||||
width: 0px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.min-w-0 {
|
.min-w-0 {
|
||||||
|
@ -1190,6 +1171,11 @@ html {
|
||||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.translate-x-5 {
|
||||||
|
--tw-translate-x: 1.25rem;
|
||||||
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||||
|
}
|
||||||
|
|
||||||
.scale-95 {
|
.scale-95 {
|
||||||
--tw-scale-x: .95;
|
--tw-scale-x: .95;
|
||||||
--tw-scale-y: .95;
|
--tw-scale-y: .95;
|
||||||
|
@ -1221,10 +1207,6 @@ html {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-flow-row {
|
|
||||||
grid-auto-flow: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-cols-6 {
|
.grid-cols-6 {
|
||||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
@ -1233,6 +1215,10 @@ html {
|
||||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
grid-template-columns: repeat(1, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grid-cols-2 {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
.grid-cols-3 {
|
.grid-cols-3 {
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
@ -1241,10 +1227,6 @@ html {
|
||||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-cols-2 {
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.flex-row {
|
.flex-row {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
@ -1344,24 +1326,18 @@ html {
|
||||||
margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse)));
|
margin-left: calc(2rem * calc(1 - var(--tw-space-x-reverse)));
|
||||||
}
|
}
|
||||||
|
|
||||||
.space-x-3 > :not([hidden]) ~ :not([hidden]) {
|
|
||||||
--tw-space-x-reverse: 0;
|
|
||||||
margin-right: calc(0.75rem * var(--tw-space-x-reverse));
|
|
||||||
margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
|
|
||||||
}
|
|
||||||
|
|
||||||
.space-x-4 > :not([hidden]) ~ :not([hidden]) {
|
|
||||||
--tw-space-x-reverse: 0;
|
|
||||||
margin-right: calc(1rem * var(--tw-space-x-reverse));
|
|
||||||
margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
|
|
||||||
}
|
|
||||||
|
|
||||||
.-space-x-px > :not([hidden]) ~ :not([hidden]) {
|
.-space-x-px > :not([hidden]) ~ :not([hidden]) {
|
||||||
--tw-space-x-reverse: 0;
|
--tw-space-x-reverse: 0;
|
||||||
margin-right: calc(-1px * var(--tw-space-x-reverse));
|
margin-right: calc(-1px * var(--tw-space-x-reverse));
|
||||||
margin-left: calc(-1px * calc(1 - var(--tw-space-x-reverse)));
|
margin-left: calc(-1px * calc(1 - var(--tw-space-x-reverse)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.space-x-3 > :not([hidden]) ~ :not([hidden]) {
|
||||||
|
--tw-space-x-reverse: 0;
|
||||||
|
margin-right: calc(0.75rem * var(--tw-space-x-reverse));
|
||||||
|
margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
|
||||||
|
}
|
||||||
|
|
||||||
.space-y-8 > :not([hidden]) ~ :not([hidden]) {
|
.space-y-8 > :not([hidden]) ~ :not([hidden]) {
|
||||||
--tw-space-y-reverse: 0;
|
--tw-space-y-reverse: 0;
|
||||||
margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));
|
margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));
|
||||||
|
@ -1374,12 +1350,6 @@ html {
|
||||||
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
|
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
|
||||||
}
|
}
|
||||||
|
|
||||||
.space-x-6 > :not([hidden]) ~ :not([hidden]) {
|
|
||||||
--tw-space-x-reverse: 0;
|
|
||||||
margin-right: calc(1.5rem * var(--tw-space-x-reverse));
|
|
||||||
margin-left: calc(1.5rem * calc(1 - var(--tw-space-x-reverse)));
|
|
||||||
}
|
|
||||||
|
|
||||||
.space-y-reverse > :not([hidden]) ~ :not([hidden]) {
|
.space-y-reverse > :not([hidden]) ~ :not([hidden]) {
|
||||||
--tw-space-y-reverse: 1;
|
--tw-space-y-reverse: 1;
|
||||||
}
|
}
|
||||||
|
@ -1478,9 +1448,9 @@ html {
|
||||||
border-bottom-right-radius: 0.375rem;
|
border-bottom-right-radius: 0.375rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-b-2xl {
|
.rounded-r-2xl {
|
||||||
|
border-top-right-radius: 1rem;
|
||||||
border-bottom-right-radius: 1rem;
|
border-bottom-right-radius: 1rem;
|
||||||
border-bottom-left-radius: 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-l-2xl {
|
.rounded-l-2xl {
|
||||||
|
@ -1488,9 +1458,9 @@ html {
|
||||||
border-bottom-left-radius: 1rem;
|
border-bottom-left-radius: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-r-2xl {
|
.rounded-b-2xl {
|
||||||
border-top-right-radius: 1rem;
|
|
||||||
border-bottom-right-radius: 1rem;
|
border-bottom-right-radius: 1rem;
|
||||||
|
border-bottom-left-radius: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.border {
|
.border {
|
||||||
|
@ -1501,10 +1471,6 @@ html {
|
||||||
border-width: 2px;
|
border-width: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-4 {
|
|
||||||
border-width: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.border-r {
|
.border-r {
|
||||||
border-right-width: 1px;
|
border-right-width: 1px;
|
||||||
}
|
}
|
||||||
|
@ -1521,18 +1487,10 @@ html {
|
||||||
border-bottom-width: 2px;
|
border-bottom-width: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-r-0 {
|
|
||||||
border-right-width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.border-l-0 {
|
.border-l-0 {
|
||||||
border-left-width: 0px;
|
border-left-width: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-dashed {
|
|
||||||
border-style: dashed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.border-gray-200 {
|
.border-gray-200 {
|
||||||
--tw-border-opacity: 1;
|
--tw-border-opacity: 1;
|
||||||
border-color: rgb(229 231 235 / var(--tw-border-opacity));
|
border-color: rgb(229 231 235 / var(--tw-border-opacity));
|
||||||
|
@ -1602,31 +1560,6 @@ html {
|
||||||
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-gray-200 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-gray-400 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(156 163 175 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-blue-500 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-green-500 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(34 197 94 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-blue-600 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(37 99 235 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-green-100 {
|
.bg-green-100 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(220 252 231 / var(--tw-bg-opacity));
|
background-color: rgb(220 252 231 / var(--tw-bg-opacity));
|
||||||
|
@ -1637,11 +1570,6 @@ html {
|
||||||
background-color: rgb(238 242 255 / var(--tw-bg-opacity));
|
background-color: rgb(238 242 255 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.bg-gray-300 {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(209 213 219 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-indigo-600 {
|
.bg-indigo-600 {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(79 70 229 / var(--tw-bg-opacity));
|
background-color: rgb(79 70 229 / var(--tw-bg-opacity));
|
||||||
|
@ -1652,6 +1580,11 @@ html {
|
||||||
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
background-color: rgb(17 24 39 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-gray-200 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(229 231 235 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-opacity-75 {
|
.bg-opacity-75 {
|
||||||
--tw-bg-opacity: 0.75;
|
--tw-bg-opacity: 0.75;
|
||||||
}
|
}
|
||||||
|
@ -1660,8 +1593,8 @@ html {
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-6 {
|
.p-12 {
|
||||||
padding: 1.5rem;
|
padding: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-2 {
|
.p-2 {
|
||||||
|
@ -1676,14 +1609,6 @@ html {
|
||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.p-8 {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.p-12 {
|
|
||||||
padding: 3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.px-4 {
|
.px-4 {
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
|
@ -1749,26 +1674,16 @@ html {
|
||||||
padding-bottom: 0.75rem;
|
padding-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.px-6 {
|
|
||||||
padding-left: 1.5rem;
|
|
||||||
padding-right: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.py-0\.5 {
|
|
||||||
padding-top: 0.125rem;
|
|
||||||
padding-bottom: 0.125rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.py-0 {
|
|
||||||
padding-top: 0px;
|
|
||||||
padding-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.py-8 {
|
.py-8 {
|
||||||
padding-top: 2rem;
|
padding-top: 2rem;
|
||||||
padding-bottom: 2rem;
|
padding-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.px-6 {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pt-5 {
|
.pt-5 {
|
||||||
padding-top: 1.25rem;
|
padding-top: 1.25rem;
|
||||||
}
|
}
|
||||||
|
@ -1809,40 +1724,28 @@ html {
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pb-8 {
|
|
||||||
padding-bottom: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pt-1\.5 {
|
|
||||||
padding-top: 0.375rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pt-1 {
|
|
||||||
padding-top: 0.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pr-4 {
|
.pr-4 {
|
||||||
padding-right: 1rem;
|
padding-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pr-2 {
|
.pr-12 {
|
||||||
padding-right: 0.5rem;
|
padding-right: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pt-8 {
|
.pt-8 {
|
||||||
padding-top: 2rem;
|
padding-top: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pr-2 {
|
||||||
|
padding-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pl-1\.5 {
|
.pl-1\.5 {
|
||||||
padding-left: 0.375rem;
|
padding-left: 0.375rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pl-3\.5 {
|
.pb-1 {
|
||||||
padding-left: 0.875rem;
|
padding-bottom: 0.25rem;
|
||||||
}
|
|
||||||
|
|
||||||
.pr-12 {
|
|
||||||
padding-right: 3rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-left {
|
.text-left {
|
||||||
|
@ -1857,6 +1760,10 @@ html {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-justify {
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
.align-middle {
|
.align-middle {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
@ -1916,10 +1823,6 @@ html {
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
}
|
}
|
||||||
|
|
||||||
.font-black {
|
|
||||||
font-weight: 900;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uppercase {
|
.uppercase {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
@ -1989,16 +1892,16 @@ html {
|
||||||
color: rgb(22 101 52 / var(--tw-text-opacity));
|
color: rgb(22 101 52 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-gray-600 {
|
|
||||||
--tw-text-opacity: 1;
|
|
||||||
color: rgb(75 85 99 / var(--tw-text-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-co-green {
|
.text-co-green {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(108 193 31 / var(--tw-text-opacity));
|
color: rgb(108 193 31 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.text-gray-600 {
|
||||||
|
--tw-text-opacity: 1;
|
||||||
|
color: rgb(75 85 99 / var(--tw-text-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.placeholder-gray-500::-moz-placeholder {
|
.placeholder-gray-500::-moz-placeholder {
|
||||||
--tw-placeholder-opacity: 1;
|
--tw-placeholder-opacity: 1;
|
||||||
color: rgb(107 114 128 / var(--tw-placeholder-opacity));
|
color: rgb(107 114 128 / var(--tw-placeholder-opacity));
|
||||||
|
@ -2058,9 +1961,9 @@ html {
|
||||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ring-8 {
|
.ring-0 {
|
||||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2101,6 +2004,14 @@ html {
|
||||||
transition-duration: 150ms;
|
transition-duration: 150ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.transition-colors {
|
||||||
|
transition-property: color, background-color, border-color, fill, stroke, -webkit-text-decoration-color;
|
||||||
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
||||||
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, -webkit-text-decoration-color;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
transition-duration: 150ms;
|
||||||
|
}
|
||||||
|
|
||||||
.duration-300 {
|
.duration-300 {
|
||||||
transition-duration: 300ms;
|
transition-duration: 300ms;
|
||||||
}
|
}
|
||||||
|
@ -2113,6 +2024,10 @@ html {
|
||||||
transition-duration: 75ms;
|
transition-duration: 75ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.duration-200 {
|
||||||
|
transition-duration: 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
.ease-linear {
|
.ease-linear {
|
||||||
transition-timing-function: linear;
|
transition-timing-function: linear;
|
||||||
}
|
}
|
||||||
|
@ -2188,21 +2103,16 @@ html {
|
||||||
background-color: rgb(36 56 135 / var(--tw-bg-opacity));
|
background-color: rgb(36 56 135 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover\:bg-blue-700:hover {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover\:bg-indigo-700:hover {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(67 56 202 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover\:bg-gray-100:hover {
|
.hover\:bg-gray-100:hover {
|
||||||
--tw-bg-opacity: 1;
|
--tw-bg-opacity: 1;
|
||||||
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover\:bg-blue-700:hover {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.hover\:bg-opacity-5:hover {
|
.hover\:bg-opacity-5:hover {
|
||||||
--tw-bg-opacity: 0.05;
|
--tw-bg-opacity: 0.05;
|
||||||
}
|
}
|
||||||
|
@ -2222,9 +2132,9 @@ html {
|
||||||
color: rgb(55 65 81 / var(--tw-text-opacity));
|
color: rgb(55 65 81 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover\:text-indigo-900:hover {
|
.hover\:text-co-blue:hover {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(49 46 129 / var(--tw-text-opacity));
|
color: rgb(36 56 135 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover\:text-gray-900:hover {
|
.hover\:text-gray-900:hover {
|
||||||
|
@ -2232,23 +2142,13 @@ html {
|
||||||
color: rgb(17 24 39 / var(--tw-text-opacity));
|
color: rgb(17 24 39 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover\:text-co-blue:hover {
|
|
||||||
--tw-text-opacity: 1;
|
|
||||||
color: rgb(36 56 135 / var(--tw-text-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover\:text-inherit:hover {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover\:text-gray-500:hover {
|
.hover\:text-gray-500:hover {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(107 114 128 / var(--tw-text-opacity));
|
color: rgb(107 114 128 / var(--tw-text-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.hover\:text-indigo-500:hover {
|
.hover\:text-inherit:hover {
|
||||||
--tw-text-opacity: 1;
|
color: inherit;
|
||||||
color: rgb(99 102 241 / var(--tw-text-opacity));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.focus\:border-transparent:focus {
|
.focus\:border-transparent:focus {
|
||||||
|
@ -2327,16 +2227,16 @@ html {
|
||||||
--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity));
|
--tw-ring-color: rgb(99 102 241 / var(--tw-ring-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
.focus\:ring-blue-500:focus {
|
|
||||||
--tw-ring-opacity: 1;
|
|
||||||
--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.focus\:ring-co-red:focus {
|
.focus\:ring-co-red:focus {
|
||||||
--tw-ring-opacity: 1;
|
--tw-ring-opacity: 1;
|
||||||
--tw-ring-color: rgb(255 19 0 / var(--tw-ring-opacity));
|
--tw-ring-color: rgb(255 19 0 / var(--tw-ring-opacity));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.focus\:ring-blue-500:focus {
|
||||||
|
--tw-ring-opacity: 1;
|
||||||
|
--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
|
||||||
|
}
|
||||||
|
|
||||||
.focus\:ring-offset-2:focus {
|
.focus\:ring-offset-2:focus {
|
||||||
--tw-ring-offset-width: 2px;
|
--tw-ring-offset-width: 2px;
|
||||||
}
|
}
|
||||||
|
@ -2367,6 +2267,10 @@ html {
|
||||||
grid-column: span 1 / span 1;
|
grid-column: span 1 / span 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sm\:col-span-6 {
|
||||||
|
grid-column: span 6 / span 6;
|
||||||
|
}
|
||||||
|
|
||||||
.sm\:mx-auto {
|
.sm\:mx-auto {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
|
@ -2437,10 +2341,6 @@ html {
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
||||||
.sm\:grid-cols-6 {
|
|
||||||
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.sm\:grid-cols-3 {
|
.sm\:grid-cols-3 {
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ func NewIdentificationProvider(cfg *viper.Viper, services *services.ServicesHand
|
||||||
Endpoint: provider.Endpoint(),
|
Endpoint: provider.Endpoint(),
|
||||||
|
|
||||||
// "openid" is a required scope for OpenID Connect flows.
|
// "openid" is a required scope for OpenID Connect flows.
|
||||||
Scopes: []string{oidc.ScopeOpenID, "groups", "profile"},
|
Scopes: []string{oidc.ScopeOpenID, "groups", "first_name", "last_name", "display_name"},
|
||||||
}
|
}
|
||||||
|
|
||||||
var store = sessions.NewCookieStore([]byte(sessionsSecret))
|
var store = sessions.NewCookieStore([]byte(sessionsSecret))
|
||||||
|
|
Loading…
Reference in New Issue