diff --git a/handlers/application/group_module.go b/handlers/application/group_module.go new file mode 100644 index 0000000..e6da0aa --- /dev/null +++ b/handlers/application/group_module.go @@ -0,0 +1,221 @@ +package application + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "sort" + "strings" + "time" + + groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi" + groupstorage "git.coopgo.io/coopgo-platform/groups-management/storage" + mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" + "github.com/google/uuid" + "github.com/gorilla/mux" + "google.golang.org/protobuf/types/known/structpb" +) + +var Addres any + +type BeneficiariesGroupForm struct { + FirstName string `json:"first_name" validate:"required"` + LastName string `json:"last_name" validate:"required"` + Email string `json:"email" validate:"required,email"` + Birthdate *time.Time `json:"birthdate"` + PhoneNumber string `json:"phone_number" validate:"required,phoneNumber"` + Address any `json:"address,omitempty"` + Gender string `json:"gender"` +} + +type GroupsModuleByName []groupstorage.Group + +func (a GroupsModuleByName) Len() int { return len(a) } +func (a GroupsModuleByName) Less(i, j int) bool { + return strings.Compare(a[i].Data["name"].(string), a[j].Data["name"].(string)) < 0 +} +func (a GroupsModuleByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } + +func (h *ApplicationHandler) Groups(w http.ResponseWriter, r *http.Request) { + + request := &groupsmanagement.GetGroupsRequest{ + Namespaces: []string{"parcoursmob_groups"}, + } + + resp, err := h.services.GRPC.GroupsManagement.GetGroups(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + var groups = []groupstorage.Group{} + + for _, group := range resp.Groups { + g := group.ToStorageType() + groups = append(groups, g) + } + + sort.Sort(GroupsModuleByName(groups)) + + h.Renderer.Groups(w, r, groups) +} + +func (h *ApplicationHandler) CreateGroupModule(w http.ResponseWriter, r *http.Request) { + if r.Method == "POST" { + if r.PostFormValue("address") != "" { + var a any + json.Unmarshal([]byte(r.PostFormValue("address")), &a) + + Addres = a + } + r.ParseForm() + + if r.FormValue("name") == "" { + + fmt.Println("invalid name") + w.WriteHeader(http.StatusBadRequest) + return + } + if r.FormValue("type") == "" { + + fmt.Println("invalid type") + w.WriteHeader(http.StatusBadRequest) + return + } + + groupid := uuid.NewString() + + dataMap := map[string]any{ + "name": r.FormValue("name"), + "type": r.FormValue("type"), + "description": r.FormValue("description"), + "address": Addres, + } + + data, err := structpb.NewValue(dataMap) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + request_organization := &groupsmanagement.AddGroupRequest{ + Group: &groupsmanagement.Group{ + Id: groupid, + Namespace: "parcoursmob_groups", + Data: data.GetStructValue(), + }, + } + + _, err = h.services.GRPC.GroupsManagement.AddGroup(context.TODO(), request_organization) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + http.Redirect(w, r, fmt.Sprintf("/app/group_module/groups/%s", groupid), http.StatusFound) + return + } + group_types := h.config.GetStringSlice("modules.groups.group_types") + h.Renderer.CreateGroupModule(w, r, group_types) +} + +func filterAcccount(r *http.Request, a *mobilityaccounts.Account) bool { + searchFilter, ok := r.URL.Query()["search"] + + if ok && len(searchFilter[0]) > 0 { + name := a.Data.AsMap()["first_name"].(string) + " " + a.Data.AsMap()["last_name"].(string) + if !strings.Contains(strings.ToLower(name), strings.ToLower(searchFilter[0])) { + return false + } + } + + return true +} +func (h *ApplicationHandler) DisplayGroupModule(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + groupid := vars["groupid"] + + request := &groupsmanagement.GetGroupRequest{ + Id: groupid, + } + + resp, err := h.services.GRPC.GroupsManagement.GetGroup(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + var accounts = []any{} + + requesst := &mobilityaccounts.GetAccountsBatchRequest{ + Accountids: resp.Group.Members, + } + + ressp, _ := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), requesst) + // if err != nil { + // return err + // } + for _, account := range ressp.Accounts { + if filterAcccount(r, account) { + a := account.ToStorageType() + accounts = append(accounts, a) + } + } + + cacheid := uuid.NewString() + h.cache.PutWithTTL(cacheid, accounts, 1*time.Hour) + r.ParseForm() + + var beneficiary any + + searched := false + + // if r.Method == "POST" { + if r.FormValue("beneficiaryid") != "" { + // Handler form + searched = true + + requestbeneficiary := &mobilityaccounts.GetAccountRequest{ + Id: r.FormValue("beneficiaryid"), + } + + respbeneficiary, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), requestbeneficiary) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + beneficiary = respbeneficiary.Account.ToStorageType() + + subscribe := &groupsmanagement.SubscribeRequest{ + Groupid: resp.Group.ToStorageType().ID, + Memberid: respbeneficiary.Account.Id, + } + + _, err = h.services.GRPC.GroupsManagement.Subscribe(context.TODO(), subscribe) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + http.Redirect(w, r, fmt.Sprintf("/app/group_module/groups/%s", resp.Group.ToStorageType().ID), http.StatusFound) + return + } + + accountsBeneficaire, err := h.beneficiaries(r) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusBadRequest) + return + } + //h.Renderer.BeneficaireSearch(w, r, accounts, searched, beneficiary, resp.Group.ToStorageType()) + h.Renderer.DisplayGroupModule(w, r, resp.Group.ToStorageType().ID, accounts, cacheid, searched, beneficiary, resp.Group.ToStorageType(), accountsBeneficaire) +} diff --git a/main.go b/main.go index 1445b74..0684d0d 100644 --- a/main.go +++ b/main.go @@ -110,6 +110,11 @@ func main() { /********************Code Supprt Emailing************************/ application.HandleFunc("/support/", applicationHandler.SupportSend) + /*********************** CODE GROUP **************************/ + appGroup := application.PathPrefix("/group_module").Subrouter() + appGroup.HandleFunc("/", applicationHandler.Groups) + appGroup.HandleFunc("/groups", applicationHandler.CreateGroupModule) + appGroup.HandleFunc("/groups/{groupid}", applicationHandler.DisplayGroupModule) /****************************************************************/ //TODO Subrouters with middlewares checking security for each module ? diff --git a/renderer/group_module.go b/renderer/group_module.go new file mode 100644 index 0000000..ba3fd03 --- /dev/null +++ b/renderer/group_module.go @@ -0,0 +1,77 @@ +package renderer + +import ( + "encoding/json" + "html/template" + "net/http" + + mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage" +) + +const groupMenu = "group_module" + +type BeneficiariesList struct { + Group string `json:"group"` + Count int `json:"count"` + CacheId string `json:"cache_id"` + Beneficiaries []any `json:"beneficiaries"` +} + +func (s BeneficiariesList) JSON() template.JS { + result, _ := json.Marshal(s) + return template.JS(result) +} + +func (s BeneficiariesList) JSONWithLimits(a int, b int) template.JS { + if b < len(s.Beneficiaries) { + s.Beneficiaries = s.Beneficiaries[a:b] + } + return s.JSON() +} + +func (renderer *Renderer) Groups(w http.ResponseWriter, r *http.Request, groups any) { + files := renderer.ThemeConfig.GetStringSlice("views.group_module.home.files") + state := NewState(r, renderer.ThemeConfig, groupMenu) + state.ViewState = map[string]any{ + "groups": groups, + } + + renderer.Render("group_module", w, r, files, state) +} + +func (renderer *Renderer) CreateGroupModule(w http.ResponseWriter, r *http.Request, group_types []string) { + files := renderer.ThemeConfig.GetStringSlice("views.group_module.create_group.files") + state := NewState(r, renderer.ThemeConfig, groupMenu) + state.ViewState = map[string]any{ + "group_types": group_types, + } + renderer.Render("group_module", w, r, files, state) +} + +func (renderer *Renderer) DisplayGroupModule(w http.ResponseWriter, r *http.Request, groupid string, accounts []any, cacheid string, searched bool, beneficiary any, group any, beneficiaries []mobilityaccountsstorage.Account) { + files := renderer.ThemeConfig.GetStringSlice("views.group_module.display_group.files") + state := NewState(r, renderer.ThemeConfig, groupMenu) + + viewstate := map[string]any{ + "beneficiaries": beneficiaries, + "searched": searched, + "group": group, + "list": BeneficiariesList{ + Group: groupid, + Count: len(accounts), + CacheId: cacheid, + Beneficiaries: accounts, + }, + } + + if searched { + viewstate["search"] = map[string]any{ + "beneficiary": beneficiary, + } + + } + + state.ViewState = viewstate + + renderer.Render("beneficiaries_list", w, r, files, state) +} diff --git a/renderer/renderer.go b/renderer/renderer.go index 16f982a..9a2b34e 100644 --- a/renderer/renderer.go +++ b/renderer/renderer.go @@ -222,6 +222,16 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende } + if modules["group_module"] != nil && modules["group_module"].(bool) { + ls.MenuItems = append(ls.MenuItems, MenuItem{ + Title: "Groupes / Communautés", + Link: "/app/group_module/", + Active: menuState == groupMenu, + Icon: "hero:outline/group_module", + }) + + } + if modules["directory"] != nil && modules["directory"].(bool) { ls.MenuItems = append(ls.MenuItems, MenuItem{ Title: "Répertoire solutions",