You've already forked golang-saas-starter-kit
mirror of
https://github.com/raseels-repos/golang-saas-starter-kit.git
synced 2025-07-15 01:34:32 +02:00
signup autocomplete
This commit is contained in:
52
cmd/web-app/handlers/api_geo.go
Normal file
52
cmd/web-app/handlers/api_geo.go
Normal file
@ -0,0 +1,52 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"geeks-accelerator/oss/saas-starter-kit/internal/platform/web"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"geeks-accelerator/oss/saas-starter-kit/internal/geonames"
|
||||
"gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis"
|
||||
)
|
||||
|
||||
// Check provides support for orchestration geo endpoints.
|
||||
type Geo struct {
|
||||
MasterDB *sqlx.DB
|
||||
Redis *redis.Client
|
||||
}
|
||||
|
||||
// RegionsAutocomplete...
|
||||
func (h *Geo) RegionsAutocomplete(ctx context.Context, w http.ResponseWriter, r *http.Request, params map[string]string) error {
|
||||
|
||||
var filters []string
|
||||
var args []interface{}
|
||||
|
||||
if qv := r.URL.Query().Get("postal_code"); qv != "" {
|
||||
filters = append(filters,"postal_code like ?")
|
||||
args = append(args, qv+"%")
|
||||
}
|
||||
|
||||
if qv := r.URL.Query().Get("query"); qv != "" {
|
||||
filters = append(filters,"(state_name like ? or state_code like ?)")
|
||||
args = append(args, qv+"%", qv+"%")
|
||||
}
|
||||
|
||||
where := strings.Join(filters, " AND ")
|
||||
|
||||
res, err := geonames.FindGeonameRegions(ctx, h.MasterDB, where, args)
|
||||
if err != nil {
|
||||
fmt.Printf("%+v", err)
|
||||
return web.RespondJsonError(ctx, w, err)
|
||||
}
|
||||
|
||||
var list []string
|
||||
for _, c := range res {
|
||||
list = append(list, c.Name)
|
||||
}
|
||||
|
||||
return web.RespondJson(ctx, w, list, http.StatusOK)
|
||||
}
|
||||
|
@ -68,6 +68,14 @@ func APP(shutdown chan os.Signal, log *log.Logger, env webcontext.Env, staticDir
|
||||
app.Handle("POST", "/signup", s.Step1)
|
||||
app.Handle("GET", "/signup", s.Step1)
|
||||
|
||||
// Register geo
|
||||
g := Geo{
|
||||
MasterDB: masterDB,
|
||||
Redis: redis,
|
||||
}
|
||||
// These routes are not authenticated
|
||||
app.Handle("GET", "/geo/regions/autocomplete", g.RegionsAutocomplete)
|
||||
|
||||
// Register root
|
||||
r := Root{
|
||||
MasterDB: masterDB,
|
||||
|
@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"geeks-accelerator/oss/saas-starter-kit/internal/geonames"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@ -80,6 +81,14 @@ func (h *Signup) Step1(ctx context.Context, w http.ResponseWriter, r *http.Reque
|
||||
|
||||
// Redirect the user to the dashboard.
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
return nil
|
||||
}
|
||||
|
||||
data["geonameCountries"] = geonames.ValidGeonameCountries
|
||||
|
||||
data["countries"], err = geonames.FindCountries(ctx, h.MasterDB, "name", "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -35,17 +35,21 @@
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-6 mb-3 mb-sm-0">
|
||||
<input type="text" class="form-control form-control-user {{ ValidationFieldClass $.validationErrors "Account.Zipcode" }}" name="Account.Zipcode" value="{{ $.form.Account.Zipcode }}" placeholder="Zipcode" required>
|
||||
{{template "invalid-feedback" dict "validationDefaults" $.validationDefaults "validationErrors" $.validationErrors "fieldName" "Account.Zipcode" }}
|
||||
<select class="form-control form-control-user {{ ValidationFieldClass $.validationErrors "Account.Country" }}" id="selectAccountCountry" name="Account.Country" placeholder="Country" required>
|
||||
{{ range $i := $.countries }}
|
||||
<option value="{{ $i.Code }}" {{ if eq $.form.Account.Country $i.Code }}selected="selected"{{ end }}>{{ $i.Name }}</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
{{template "invalid-feedback" dict "validationDefaults" $.validationDefaults "validationErrors" $.validationErrors "fieldName" "Account.Country" }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-6 mb-3 mb-sm-0">
|
||||
<input type="text" class="form-control form-control-user {{ ValidationFieldClass $.validationErrors "Account.Country" }}" name="Account.Country" value="{{ $.form.Account.Country }}" placeholder="Country" required>
|
||||
{{template "invalid-feedback" dict "validationDefaults" $.validationDefaults "validationErrors" $.validationErrors "fieldName" "Account.Country" }}
|
||||
<input type="text" class="form-control form-control-user {{ ValidationFieldClass $.validationErrors "Account.Zipcode" }}" id="inputAccountZipcode" name="Account.Zipcode" value="{{ $.form.Account.Zipcode }}" placeholder="Zipcode" required>
|
||||
{{template "invalid-feedback" dict "validationDefaults" $.validationDefaults "validationErrors" $.validationErrors "fieldName" "Account.Zipcode" }}
|
||||
</div>
|
||||
<div class="col-sm-6 mb-3 mb-sm-0">
|
||||
<input type="text" class="form-control form-control-user {{ ValidationFieldClass $.validationErrors "Account.Region" }}" name="Account.Region" value="{{ $.form.Account.Region }}" placeholder="Region" required>
|
||||
<input type="text" class="form-control form-control-user {{ ValidationFieldClass $.validationErrors "Account.Region" }}" id="inputAccountRegion" name="Account.Region" value="{{ $.form.Account.Region }}" placeholder="Region" required>
|
||||
{{template "invalid-feedback" dict "validationDefaults" $.validationDefaults "validationErrors" $.validationErrors "fieldName" "Account.Region" }}
|
||||
</div>
|
||||
</div>
|
||||
@ -103,13 +107,71 @@
|
||||
</div>
|
||||
{{end}}
|
||||
{{define "js"}}
|
||||
<script src="https://cdn.jsdelivr.net/gh/xcash/bootstrap-autocomplete@v2.2.2/dist/latest/bootstrap-autocomplete.min.js"></script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(document).find('body').addClass('bg-gradient-primary');
|
||||
|
||||
var regionAutocompleteParams = null;
|
||||
var countryAutocompleteParams = null;
|
||||
|
||||
$('#inputAccountZipcode').on('change', function () {
|
||||
console.log($(this).val());
|
||||
|
||||
regionAutocompleteParams = {postal_code: $(this).val()};
|
||||
$('#inputAccountRegion').keyup();
|
||||
|
||||
countryAutocompleteParams = {postal_code: $(this).val()};
|
||||
$('#inputAccountCountry').keyup();
|
||||
});
|
||||
|
||||
$('#inputAccountRegion').on('keydown', function () {
|
||||
regionAutocompleteParams = null;
|
||||
});
|
||||
|
||||
$('#inputAccountCountry').on('keydown', function () {
|
||||
countryAutocompleteParams = null;
|
||||
});
|
||||
|
||||
$('#inputAccountRegion').autoComplete({
|
||||
events: {
|
||||
search: function (qry, callback) {
|
||||
if (regionAutocompleteParams === null) {
|
||||
regionAutocompleteParams = {query: qry};
|
||||
}
|
||||
|
||||
$.ajax(
|
||||
'/geo/regions/autocomplete',
|
||||
{
|
||||
data: regionAutocompleteParams
|
||||
}
|
||||
).done(function (res) {
|
||||
callback(res)
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#inputAccountCountry').autoComplete({
|
||||
events: {
|
||||
search: function (qry, callback) {
|
||||
if (countryAutocompleteParams === null) {
|
||||
countryAutocompleteParams = {query: qry};
|
||||
}
|
||||
|
||||
$.ajax(
|
||||
'/geo/countries/autocomplete',
|
||||
{
|
||||
data: countryAutocompleteParams
|
||||
}
|
||||
).done(function (res) {
|
||||
callback(res)
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// console.log(($('input[name=\'Account\.Name\']').parent().find('.invalid-feedback').show()));
|
||||
|
||||
});
|
||||
</script>
|
||||
|
@ -31,8 +31,8 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox small">
|
||||
<input type="checkbox" class="custom-control-input" id="checkRemberMe" name="RememberMe" value="1" {{ if $.form.RememberMe }}checked="checked"{{end}}>
|
||||
<label class="custom-control-label" for="checkRemberMe">Remember Me</label>
|
||||
<input type="checkbox" class="custom-control-input" id="inputRemberMe" name="RememberMe" value="1" {{ if $.form.RememberMe }}checked="checked"{{end}}>
|
||||
<label class="custom-control-label" for="inputRemberMe">Remember Me</label>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary btn-user btn-block">
|
||||
|
@ -17,7 +17,7 @@
|
||||
<!-- ============================================================== -->
|
||||
<!-- Custom fonts for this template -->
|
||||
<!-- ============================================================== -->
|
||||
<link href="{{ SiteAssetUrl "/assets/vendor/fontawesome-free/css/all.min.css" }}" rel="stylesheet" type="text/css">
|
||||
<script src="https://kit.fontawesome.com/670ea91c67.js"></script>
|
||||
<link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">
|
||||
|
||||
<!-- ============================================================== -->
|
||||
|
Reference in New Issue
Block a user