Split comparison, summary, and header sections into seperate files to reuse headers more easily and make future changes easier.master
@@ -223,7 +223,10 @@ func cachePdf(name string) Page { | |||||
} | } | ||||
fm := template.FuncMap{ "dollars": dollars, "diff": diff } | fm := template.FuncMap{ "dollars": dollars, "diff": diff } | ||||
var p = []string{"views/report/master.tpl", paths[name]} | |||||
var p = []string{"views/report/master.tpl", | |||||
"views/report/header.tpl", | |||||
"views/report/summary.tpl", | |||||
"views/report/comparison.tpl"} | |||||
tpl := template.Must(template.New("master.tpl").Funcs(fm).ParseFiles(p...)) | tpl := template.Must(template.New("master.tpl").Funcs(fm).ParseFiles(p...)) | ||||
return Page{ tpl: tpl, Title: "", Name: name } | return Page{ tpl: tpl, Title: "", Name: name } | ||||
@@ -1,138 +1,9 @@ | |||||
{{define "header"}} | |||||
{{end}} | |||||
{{define "main"}} | |||||
<div id="pdf-doc"> | |||||
<div class="disclaimer"><p>Actual costs may vary from estimates after approval. Get an official quote before choosing a loan.</p></div> | |||||
<header class="heading"> | |||||
<img src="data:image/png;base64,{{.Letterhead}}" /> | |||||
<div> | |||||
<div class="user-info"> | |||||
<h4>{{.User.FirstName}} {{.User.LastName}}</h4> | |||||
<span>{{.User.Email}}</span> | |||||
<span>{{.User.Phone}}</span> | |||||
<small>{{.User.Address.Street}}</small> | |||||
<small> | |||||
{{.User.Address.City}}, {{.User.Address.Region}} {{.User.Address.Zip}} | |||||
</small> | |||||
</div> | |||||
<img src="data:image/png;base64,{{.Avatar}}" /> | |||||
</div> | |||||
</header> | |||||
<table> | |||||
<thead><tr> | |||||
<th></th>{{range $l := .Estimate.Loans}}<th>{{$l.Name}}</th>{{end}} | |||||
</tr></thead> | |||||
<tbody> | |||||
<tr><td>Type</td> | |||||
{{range .Estimate.Loans}}<td>{{.Type.Name}}</td>{{end}}</tr> | |||||
<tr><td>Term</td> | |||||
{{range .Estimate.Loans}}<td>{{.Term}} Years</td>{{end}}</tr> | |||||
<tr><td>Amortization</td> | |||||
{{range .Estimate.Loans}}<td>{{.Amortization}}</td>{{end}}</tr> | |||||
<tr><td>Interest rate</td> | |||||
{{range .Estimate.Loans}}<td>{{.Interest}}%</td>{{end}}</tr> | |||||
<tr><td>Monthly MI</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Mi.Premium}}/month</td>{{end}}</tr> | |||||
<tr><td>Real estate taxes</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Tax}}</td>{{end}}</tr> | |||||
<tr class="total"><td>Total monthly payment</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Result.TotalMonthly}}</td>{{end}}</tr> | |||||
<tr class="gap"></tr> | |||||
<tr><td>Purchase price</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars $.Estimate.Price}}</td>{{end}}</tr> | |||||
<tr><td>Loan amount</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Amount}}</td>{{end}}</tr> | |||||
<tr><td>Down payment</td> | |||||
{{range .Estimate.Loans}}<td>${{diff .Amount $.Estimate.Price}}</td>{{end}}</tr> | |||||
<tr><td>Closing costs</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Result.TotalFees}}</td>{{end}}</tr> | |||||
<tr><td>MI Premium</td> | |||||
{{range .Estimate.Loans}}<td>${{.Mi.Upfront}}</td>{{end}}</tr> | |||||
<tr><td>Credits</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Result.TotalCredits}}</td>{{end}}</tr> | |||||
</tbody> | |||||
</table> | |||||
<div class="break"></div> | |||||
<section class="summary"> | |||||
{{define "comparison"}} | |||||
<section class="comparison"> | |||||
<div class="box"> | <div class="box"> | ||||
hello | hello | ||||
</div> | </div> | ||||
</section> | </section> | ||||
<style scoped> | |||||
#pdf-doc { | |||||
margin: 4px 30px; | |||||
} | |||||
.disclaimer { | |||||
font-weight: bold; | |||||
border-bottom: 1px solid lightgrey; | |||||
margin-bottom: 20px; | |||||
color: var(--text); | |||||
text-align: center; | |||||
} | |||||
.disclaimer p { | |||||
margin: 5px 0; | |||||
} | |||||
h4 { | |||||
margin: 4px 0; | |||||
} | |||||
header.heading { | |||||
display: flex; | |||||
justify-content: space-between; | |||||
} | |||||
.user-info { | |||||
display: flex; | |||||
flex-flow: column; | |||||
} | |||||
#pdf-doc header.heading > div { | |||||
display: flex; | |||||
text-align: right; | |||||
} | |||||
header.heading .user-info { | |||||
margin-right: 8px; | |||||
} | |||||
table { | |||||
width: 100%; | |||||
margin-top: 20px; | |||||
} | |||||
tr.gap { | |||||
height: 20px; | |||||
} | |||||
table td:first-child { | |||||
font-weight: bold; | |||||
} | |||||
tbody tr:nth-child(odd) { | |||||
background: #F5F5F3; | |||||
} | |||||
table td { | |||||
padding: 4px; | |||||
} | |||||
div.break { | |||||
page-break-after: always; | |||||
} | |||||
</style> | |||||
{{end}} | {{end}} | ||||
@@ -0,0 +1,46 @@ | |||||
{{define "header"}} | |||||
<header class="heading"> | |||||
<img src="data:image/png;base64,{{.Letterhead}}" /> | |||||
<div> | |||||
<div class="user-info"> | |||||
<h4>{{.User.FirstName}} {{.User.LastName}}</h4> | |||||
<span>{{.User.Email}}</span> | |||||
<span>{{.User.Phone}}</span> | |||||
<small>{{.User.Address.Street}}</small> | |||||
<small> | |||||
{{.User.Address.City}}, {{.User.Address.Region}} {{.User.Address.Zip}} | |||||
</small> | |||||
</div> | |||||
<img src="data:image/png;base64,{{.Avatar}}" /> | |||||
</div> | |||||
</header> | |||||
<style scoped> | |||||
h4 { | |||||
margin: 4px 0; | |||||
} | |||||
header.heading > div { | |||||
display: flex; | |||||
text-align: right; | |||||
} | |||||
header.heading .user-info { | |||||
margin-right: 8px; | |||||
} | |||||
header.heading { | |||||
display: flex; | |||||
justify-content: space-between; | |||||
} | |||||
.user-info { | |||||
display: flex; | |||||
flex-flow: column; | |||||
} | |||||
</style> | |||||
{{end}} |
@@ -5,9 +5,45 @@ | |||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"> | content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||||
</head> | </head> | ||||
<body> | |||||
{{block "header" .}} | |||||
{{end}} | |||||
<body id="pdf-doc"> | |||||
{{template "main" .}} | |||||
<div class="disclaimer"> | |||||
<p>Actual costs may vary from estimates after approval. | |||||
Get an official quote before choosing a loan.</p> | |||||
</div> | |||||
{{template "header" .}} | |||||
{{template "summary" .}} | |||||
<div class="break"></div> | |||||
<div class="disclaimer"> | |||||
<p>Actual costs may vary from estimates after approval. | |||||
Get an official quote before choosing a loan.</p> | |||||
</div> | |||||
{{template "header" .}} | |||||
{{template "comparison" .}} | |||||
<div class="break"></div> | |||||
</body> | </body> | ||||
<style> | |||||
#pdf-doc { | |||||
margin: 0px 30px; | |||||
} | |||||
.disclaimer { | |||||
font-weight: bold; | |||||
border-bottom: 1px solid lightgrey; | |||||
margin-bottom: 20px; | |||||
color: var(--text); | |||||
text-align: center; | |||||
} | |||||
.disclaimer p { | |||||
margin: 5px 0; | |||||
} | |||||
div.break { | |||||
page-break-after: always; | |||||
} | |||||
</style> |
@@ -0,0 +1,69 @@ | |||||
{{define "summary"}} | |||||
<section id="summary"> | |||||
<table> | |||||
<thead><tr> | |||||
<th></th>{{range $l := .Estimate.Loans}}<th>{{$l.Name}}</th>{{end}} | |||||
</tr></thead> | |||||
<tbody> | |||||
<tr><td>Type</td> | |||||
{{range .Estimate.Loans}}<td>{{.Type.Name}}</td>{{end}}</tr> | |||||
<tr><td>Term</td> | |||||
{{range .Estimate.Loans}}<td>{{.Term}} Years</td>{{end}}</tr> | |||||
<tr><td>Amortization</td> | |||||
{{range .Estimate.Loans}}<td>{{.Amortization}}</td>{{end}}</tr> | |||||
<tr><td>Interest rate</td> | |||||
{{range .Estimate.Loans}}<td>{{.Interest}}%</td>{{end}}</tr> | |||||
<tr><td>Monthly MI</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Mi.Premium}}/month</td>{{end}}</tr> | |||||
<tr><td>Real estate taxes</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Tax}}/month</td>{{end}}</tr> | |||||
<tr class="total"><td>Total monthly</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Result.TotalMonthly}}</td>{{end}}</tr> | |||||
<tr class="gap"></tr> | |||||
<tr><td>Purchase price</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars $.Estimate.Price}}</td>{{end}}</tr> | |||||
<tr><td>Loan amount</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Amount}}</td>{{end}}</tr> | |||||
<tr><td>Down payment</td> | |||||
{{range .Estimate.Loans}}<td>${{diff .Amount $.Estimate.Price}}</td>{{end}}</tr> | |||||
<tr><td>Closing costs</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Result.TotalFees}}</td>{{end}}</tr> | |||||
<tr><td>MI Premium</td> | |||||
{{range .Estimate.Loans}}<td>${{.Mi.Upfront}}</td>{{end}}</tr> | |||||
<tr><td>Credits</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Result.TotalCredits}}</td>{{end}}</tr> | |||||
<tr class="total"><td>Cash to close</td> | |||||
{{range .Estimate.Loans}}<td>${{dollars .Result.CashToClose}}</td>{{end}}</tr> | |||||
</tbody> | |||||
</table> | |||||
</section> | |||||
<style scoped> | |||||
table { | |||||
width: 100%; | |||||
margin-top: 20px; | |||||
} | |||||
tr.gap { | |||||
height: 20px; | |||||
} | |||||
tr.total { | |||||
text-decoration: underline; | |||||
font-weight: bold; | |||||
} | |||||
table td:first-child { | |||||
font-weight: bold; | |||||
} | |||||
tbody tr:nth-child(odd) { | |||||
background: #F5F5F3; | |||||
} | |||||
table td { | |||||
padding: 4px; | |||||
} | |||||
</style> | |||||
{{end}} |