web.scm 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. (add-to-load-path (dirname (current-filename)))
  2. (use-modules (web server)
  3. (web request)
  4. (web response)
  5. (web uri)
  6. (decode)
  7. (oop goops)
  8. (sxml simple))
  9. (define navbar
  10. '(nav (@ (class "navbar navbar-expand-lg navbar-light bg-light"))
  11. (a (@ (class "navbar-brand")) "My IFT")
  12. (button (@ (class "navbar-toggler")
  13. (type "button")
  14. (data-toggle "collapse")
  15. (data-target "#navbarSupportedContent")
  16. (aria-controls "navbarSupportedContent")
  17. (aria-expanded "false")
  18. (aria-label "Toggle navigation"))
  19. (span (@ (class "navbar-toggler-icon")))
  20. )
  21. (div (@ (class "collapse navbar-collapse")
  22. (id "navbarSupportedcontent"))
  23. (ul (@ (class ("navbar-nav mr-auto")))
  24. (li (@ (class "nav-item active"))
  25. (a (@ (class "nav-link")
  26. (href "#"))
  27. "click me"))
  28. (li (@ (class "nav-item"))
  29. (a (@ (class "nav-link")
  30. (href "#"))
  31. "click me"))))))
  32. (define (templatize title body)
  33. `(html (head (title ,title)
  34. (head
  35. (link
  36. (@ (rel "stylesheet")
  37. ;;(href "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css")
  38. (href "localhost:8081/css/bootstrap.min.css"))
  39. ))
  40. (body ,navbar ,@body))))
  41. (define (insert-option-values values)
  42. (if (null? values) '()
  43. (let ([value (car values)])
  44. (cons `(options (@ (value ,value))
  45. ,value)
  46. (insert-option-values (cdr values))))))
  47. (define* (my-select id options
  48. #:key
  49. (required #t))
  50. `(select (@ (id ,id)
  51. (name ,id)
  52. ,(if (eq? required #t)
  53. '(required)
  54. '(not-required))
  55. (class "custom-select"))
  56. (option (@ (value "")
  57. (selected ""))
  58. "Choose...")
  59. ,(let loop ([options options])
  60. (if (null? options)
  61. '()
  62. (cons `(option (@ (value ,(car options)))
  63. ,(car options))
  64. (loop (cdr options)))))))
  65. ;; (define-syntax m-basic-form-group
  66. ;; (syntax-rules ()
  67. ;; [(m-basic-form-group the-label id)
  68. ;; '(div (@ (class "form-row"))
  69. ;; (div (@ (class "col-md-8"))
  70. ;; (label the-label)
  71. ;; (input (@ (class "form-control")))
  72. ;; ))]
  73. ;; [(m-basic-form-group the-label id ...)
  74. ;; (begin
  75. ;; '(div (@ (class "col-md-3"))
  76. ;; (label the-label)
  77. ;; (input (@ (class "form-control"))))
  78. ;; (m-basic-form-group the-label id ...))]))
  79. (define* (my-input input-type label id
  80. #:optional values
  81. #:key
  82. (placeholder "")
  83. (required #t))
  84. (let ([input-type input-type])
  85. (if (eq? input-type "select")
  86. (my-select id values #:required required)
  87. `(input (@ (id ,id)
  88. (name ,id)
  89. (type ,input-type)
  90. (class "form-control")
  91. ,(if (eq? required #t)
  92. '(required)
  93. '(not-required))
  94. (placeholder ,placeholder))))))
  95. (define* (basic-form-group label id
  96. #:key
  97. (input-type "text")
  98. (placeholder "")
  99. (required #t)
  100. values
  101. (width 8))
  102. `(div (@ (class ,(string-append "form-group col-md-"
  103. (number->string width))))
  104. (label ,label)
  105. ,(my-input input-type label id values #:required required)
  106. ;;(input (@ (class "form-control") (placeholder ,placeholder)))
  107. ))
  108. (define* (horizontal-form-group label id
  109. #:key
  110. (form-class "row")
  111. placeholder
  112. (input-type "text")
  113. (required #t)
  114. values
  115. )
  116. `(div (@ (class "form-group row"))
  117. (label (@ (class "col-md-2")
  118. (for ,id))
  119. ,label)
  120. (div (@ (class "col-md-6"))
  121. ,(my-input input-type label id values #:required required)
  122. (div (@ (class "valid-feedback"))
  123. "Looks good!"))))
  124. (define* (respond #:optional body #:key
  125. (status 200)
  126. (title "My IFT")
  127. (doctype "<!DOCTYPE html>\n")
  128. (content-type-params '((charset . "utf-8")))
  129. (content-type 'text/html)
  130. (extra-headers '())
  131. (sxml (and body (templatize title body))))
  132. (values (build-response
  133. #:code status
  134. #:headers `((content-type
  135. . (,content-type ,@content-type-params))
  136. ,@extra-headers))
  137. (lambda (port)
  138. (if sxml
  139. (begin
  140. (if doctype (display doctype port))
  141. (sxml->xml sxml port))))))
  142. (define (request-path-components request)
  143. (split-and-decode-uri-path (uri-path (request-uri request))))
  144. ;; Paste this in your REPL
  145. (define (not-found request)
  146. (values (build-response #:code 404)
  147. (string-append "Resource not found: "
  148. (uri->string (request-uri request)))))
  149. (define (test-form)
  150. (respond
  151. `((div (@ (class "container"))
  152. (div (@ (class "row")))
  153. (div (@ (class "col-md-12"))
  154. (form (@ (method "post")
  155. (action "submit1")
  156. (id "test-form"))
  157. ,(horizontal-form-group "Your first name" "first-name"
  158. #:placeholder "Jason"
  159. #:required #t)
  160. ,(horizontal-form-group "Your last name" "last-name"
  161. #:placeholder "Jason"
  162. #:required #f)
  163. (div (@ (class "row"))
  164. (div (@ (class "col-md-2"))
  165. (button (@ (class "btn btn-primary"))
  166. "Submit")))
  167. ))))))
  168. (define (main-page)
  169. (respond
  170. `((div (@ (class "container"))
  171. (div (@ (class "row"))
  172. (div (@ (class "col-md-12"))
  173. (h1 "Apply for a loan")
  174. (form (@ (method "get")
  175. (action "submit"))
  176. ,(horizontal-form-group "Your first name" "first-name"
  177. #:placeholder "James")
  178. ,(horizontal-form-group "Your last name" "last-name"
  179. #:placeholder "Jones")
  180. ,(horizontal-form-group "Your number" "number"
  181. #:placeholder "765 293 4930")
  182. ,(horizontal-form-group "Your email" "email"
  183. #:placeholder "youremail@gmail.com"
  184. #:input-type "email")
  185. ,(horizontal-form-group "Address" "address1"
  186. #:placeholder "123 Main Street")
  187. ,(horizontal-form-group "Address Line 2" "address1"
  188. #:placeholder "123 Main Street")
  189. (div (@ (class "form-row"))
  190. ,(basic-form-group "City" "city" #:width 4)
  191. ,(basic-form-group "State" "state" #:width 2)
  192. ,(basic-form-group "Zip" "zip" #:width 2)
  193. )
  194. ,(horizontal-form-group "Are you a U.S. Citizen?" "state"
  195. #:input-type "select"
  196. #:values '("No" "Yes"))
  197. ,(basic-form-group "Borrower's Fico Score? (Please list all borrowers scores)"
  198. "fico")
  199. ,(basic-form-group "Company name the borrower is closing in? (must close in a corporate entity)"
  200. "company")
  201. ,(basic-form-group "Who makes up the entity and what are their percentages of ownership?"
  202. "percentages")
  203. (div (@ (class "form-row"))
  204. ,(basic-form-group "Do you own any other investment properties?"
  205. "own"
  206. #:width 6)
  207. ,(basic-form-group "If yes, how many?"
  208. "own-number"
  209. #:width 2
  210. #:required #f))
  211. ,(basic-form-group
  212. "Does the borrower have any Tax liens, judgments, past bankruptcies, past chapter filings, past foreclosures, recent or pending lawsuits against them?"
  213. "past-problems"
  214. #:input-type "select"
  215. #:values '("No" "Yes"))
  216. (div (@ (class "row"))
  217. (div (@ (class "col-md-2"))
  218. (button (@ (class "btn btn-primary"))
  219. "Submit")))
  220. )))))))
  221. (define (verify-body body)
  222. (let ([post-data (decode body)]
  223. [data-integrity? #t])
  224. (map (lambda (element)
  225. (let ([name (car element)]
  226. [value (car (cdr element))])
  227. (display "body is \n")
  228. (display post-data)
  229. (display "\nelement is \n")
  230. (display element)
  231. (display "\nname is \n")
  232. (display name)
  233. (display "\n value is \n")
  234. (display value)
  235. (display "\n cdr of element is \n")
  236. (display (cdr element))
  237. (display "\n length of element is\n")
  238. (display (length element))
  239. (display "\ntype of value is\n")
  240. (display (class-of (cdr element)))
  241. (when (> 1 (length element))
  242. (display "it is nil!")
  243. (set! data-integrity? #f)
  244. )))
  245. post-data)
  246. ))
  247. (define (run-page request body)
  248. ;;(display (request-path-components request))
  249. (let ([current-page (request-path-components request)])
  250. (cond [(equal? current-page '())
  251. (main-page)]
  252. [(equal? current-page '("hacker"))
  253. (respond '((h1 "Hello Hacker!")))]
  254. [(equal? current-page '("submit"))
  255. (if (eq? (verify-request (request)) #t)
  256. (respond '((h1 "Submit page")))
  257. (main-page))]
  258. [(equal? current-page '("test-form"))
  259. (test-form)]
  260. [(equal? current-page '("submit1"))
  261. (verify-body body)
  262. (respond '((h1 "Testing")))]
  263. [(equal? current-page '("css" "bootstrap.min.css"))
  264. (values '((content-type . (text/plain)))
  265. "css")]
  266. [(equal? current-page '("hello"))
  267. (values '((content-type . (text/plain)))
  268. "Hello hacker!")]
  269. [else
  270. (respond `((h1 "Page not found.")
  271. (h1 ,(let loop ([current-page current-page])
  272. (if (null? current-page) ""
  273. (string-append (car current-page) "/"
  274. (loop (cdr current-page))))))))])))
  275. (run-server run-page 'http '(#:port 8081) ; '(#:host="localhost")
  276. )