본문 바로가기

GO lang/web Structure Sample

[GO] web Basic Structure 업글.

이전 게시글에서 약간의 수정을하여 Reservation summary 화면을 추가한 버전입니다.

 

수정파일 - main.go, routes.go, handlers.go, render.go, base.layout.tmpl, forms.go

신규파일 - reservation-summary.page.tmpl

 

main.go 추가 사항 - gob.Register(models.Reservation{}) 추가함

 

func main() {

	// 예약화면의 처리결과를 session 을 통해서 summary 화면으로 전달
	gob.Register(models.Reservation{})

	// change this to true when in production, 보안강화 적용안함.
	app.InProduction = false

	// 세션관련 설정
	session = scs.New()
	session.Lifetime = 24 * time.Hour
	session.Cookie.Persist = true
	session.Cookie.SameSite = http.SameSiteLaxMode
	session.Cookie.Secure = app.InProduction // middleware.go > Secure 에서도 참조함
	app.Session = session

 

routes.go - mux.Get("/reservation-summary", handlers.Repo.ReservationSummary) 추가함

 

func routes(app *config.AppConfig) http.Handler {

	mux := chi.NewRouter()
	mux.Use(middleware.Recoverer)
	mux.Use(NoSurf)
	mux.Use(SessionLoad)

	mux.Get("/make-reservation", handlers.Repo.Reservation)
	mux.Post("/make-reservation", handlers.Repo.PostReservation)
	mux.Get("/reservation-summary", handlers.Repo.ReservationSummary)

	fileServer := http.FileServer(http.Dir("./static/"))
	mux.Handle("/static/*", http.StripPrefix("/static", fileServer))

	return mux

 

handlers.go - PostReservation 마지막 2줄, ReservationSummary 함수 전체, MinLength 파라미터 변경

 

// PostReservation handles the posting of a reservation form
// post 에 대한 응답시, 필드 데이터를 검증하여 오류시 오류 메시지 및 원래 데이터를 전달한다.
func (m *Repository) PostReservation(w http.ResponseWriter, r *http.Request) {
	err := r.ParseForm()
	if err != nil {
		log.Println(err)
		return
	}

	// post 로 전달된 데이터 저장, 아래에서 응답시 화면으로 전달함
	reservation := models.Reservation{
		FirstName: r.Form.Get("first_name"),
		LastName:  r.Form.Get("last_name"),
		Email:     r.Form.Get("email"),
		Phone:     r.Form.Get("phone"),
	}
	log.Println("reservation >>", reservation)

	// 각 필드데이터에 접근은 아래처럼 해도 된다.
	form := forms.New(r.PostForm)
	log.Println("handlers.go >>> forms.New:", form.Get("first_name"))

	// form.Has("first_name")
	form.Required("first_name", "last_name", "email")
	form.MinLength("first_name", 3) /*변경사항*/
	form.IsEmail("email")

	if !form.Valid() { // 해당 폼에 오류 메시지가 하나도 없어야 실행됨
		log.Println("!form.Valid()")
		data := make(map[string]interface{})
		data["reservation"] = reservation

		render.RenderTemplate(w, r, "make-reservation.page.tmpl", &models.TemplateData{
			Form: form,
			Data: data,
		})
		return
	}
/*추가사항*/
	m.App.Session.Put(r.Context(), "reservation", reservation)
	http.Redirect(w, r, "/reservation-summary", http.StatusSeeOther)
/*추가사항*/
}

/*추가사항*/
func (m *Repository) ReservationSummary(w http.ResponseWriter, r *http.Request) {
	reservation, ok := m.App.Session.Get(r.Context(), "reservation").(models.Reservation)
	if !ok {
		log.Println("can not get the items from session")
		m.App.Session.Put(r.Context(), "error", "Can't get reservation from session")
		http.Redirect(w, r, "/make-reservation", http.StatusTemporaryRedirect)

		return
	}

	m.App.Session.Remove(r.Context(), "reservation")

	data := make(map[string]interface{})
	data["reservation"] = reservation

	render.RenderTemplate(w, r, "reservation-summary.page.tmpl", &models.TemplateData{
		Data: data,
	})
}
/*추가사항*/

 

render.go - Flash, Error, Warning 추가

 

// AddDefaultData adds data for all templates
func AddDefaultData(td *models.TemplateData, r *http.Request) *models.TemplateData {
	// <input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
	// 아래 부분이 html 에서 불러오는 이름("{{.CSRFToken}}")과 같아야 함.
	td.CSRFToken = nosurf.Token(r)
	td.Flash = app.Session.PopString(r.Context(), "flash")
	td.Error = app.Session.PopString(r.Context(), "error")
	td.Warning = app.Session.PopString(r.Context(), "warning")
	return td
}

 

base.layout.tmpl - /* 추가사항 */

 

    function notifyModal(title, text, icon, confirmButtonText) {
      Swal.fire({
        title: title,
        html: text,
        icon: icon,
        confirmButtonText: confirmButtonText
      })
    }
/* 추가사항 */
    {{with .Error}}
      notify("error", "{{.}}")
    {{end}}

    {{with .Flash}}
      notify("success", "{{.}}")
    {{end}}

    {{with .Warning}}
      notify("warning", "{{.}}")
    {{end}}
/* 추가사항 */
    function Prompt() {
      let toast = function(c) {
        const {
          msg = "",
          icon = "success",
          position = "top-end",
        } = c;

 

forms.go - 전달 파라미터 변경

 

// MinLength checks for string minimum length
func (f *Form) MinLength(field string, length int) bool {

	x := f.Get(field)
	if len(x) < length {
		f.Errors.Add(field, fmt.Sprintf("This field must be more than %d characters", length))
		return false
	}
	return true
}

 

reservation-summary.page.tmpl - 신규 화면

 

{{template "base" .}}

{{define "content"}}
{{$res := index .Data "reservation"}}
    <div class="container">
        <div class="row">
            <div class="col">
                <h1 class="mt-5">Reservation Summary</h1>

                <hr>

                <table class="table table-striped">
                    <thead></thead>
                    <tbody>
                        <tr>
                            <td>Name:</td>
                            <td>{{$res.FirstName}} {{$res.LastName}}</td>
                        </tr>

                        <tr>
                            <td>Arrival:</td>
                            <td></td>
                        </tr>

                        <tr>
                            <td>Departure:</td>
                            <td></td>
                        </tr>

                        <tr>
                            <td>Email:</td>
                            <td>{{$res.Email}}</td>
                        </tr>

                        <tr>
                            <td>Phone:</td>
                            <td>{{$res.Phone}}</td>
                        </tr>

                    </tbody>
                </table>
            </div>
        </div>
    </div>
{{end}}

 

예약화면에서 정상 입력 예시

 

 

요약화면 예시

 

 

 

 

 

 

[해당 소스 코드]

'GO lang > web Structure Sample' 카테고리의 다른 글

[GO] web Basic Structure  (0) 2021.12.17