aboutsummaryrefslogtreecommitdiffstats
path: root/src/Pages
diff options
context:
space:
mode:
Diffstat (limited to 'src/Pages')
-rw-r--r--src/Pages/Errors/Index.cshtml33
-rw-r--r--src/Pages/Errors/Index.cshtml.cs19
-rw-r--r--src/Pages/Handlekorg.cshtml100
-rw-r--r--src/Pages/Handlekorg.cshtml.cs8
-rw-r--r--src/Pages/Index.cshtml41
-rw-r--r--src/Pages/Index.cshtml.cs34
-rw-r--r--src/Pages/Kontoret/Bestillinger.cshtml67
-rw-r--r--src/Pages/Kontoret/Bestillinger.cshtml.cs8
-rw-r--r--src/Pages/Kontoret/Dokumenter.cshtml21
-rw-r--r--src/Pages/Kontoret/Dokumenter.cshtml.cs8
-rw-r--r--src/Pages/Kontoret/Produkter.cshtml18
-rw-r--r--src/Pages/Kontoret/Produkter.cshtml.cs8
-rw-r--r--src/Pages/Kontoret/_ViewImports.cshtml3
-rw-r--r--src/Pages/Kontoret/_ViewStart.cshtml3
-rw-r--r--src/Pages/Leverandorar.cshtml9
-rw-r--r--src/Pages/Leverandorar.cshtml.cs23
-rw-r--r--src/Pages/LoggInn.cshtml34
-rw-r--r--src/Pages/LoggInn.cshtml.cs19
-rw-r--r--src/Pages/OmOss.cshtml9
-rw-r--r--src/Pages/OmOss.cshtml.cs23
-rw-r--r--src/Pages/Partials/_AdminCategoriesModal.cshtml25
-rw-r--r--src/Pages/Partials/_AdminProductModal.cshtml72
-rw-r--r--src/Pages/Partials/_CultureSelector.cshtml35
-rw-r--r--src/Pages/Personvern.cshtml8
-rw-r--r--src/Pages/Personvern.cshtml.cs25
-rw-r--r--src/Pages/Produktar.cshtml163
-rw-r--r--src/Pages/Produktar.cshtml.cs82
-rw-r--r--src/Pages/SalesTerms.cshtml9
-rw-r--r--src/Pages/SalesTerms.cshtml.cs25
-rw-r--r--src/Pages/Shared/_AdminLayout.cshtml114
-rw-r--r--src/Pages/Shared/_PublicLayout.cshtml152
-rw-r--r--src/Pages/Status.cshtml136
-rw-r--r--src/Pages/Status.cshtml.cs53
-rw-r--r--src/Pages/_ViewImports.cshtml3
-rw-r--r--src/Pages/_ViewStart.cshtml3
35 files changed, 1393 insertions, 0 deletions
diff --git a/src/Pages/Errors/Index.cshtml b/src/Pages/Errors/Index.cshtml
new file mode 100644
index 0000000..5db7b59
--- /dev/null
+++ b/src/Pages/Errors/Index.cshtml
@@ -0,0 +1,33 @@
+@page "{code}"
+@using System.Net
+@model VSH.Pages.Errors.Index
+@{
+ ViewData["Title"] = Model.ErrorStatusCode switch {
+ HttpStatusCode.NotFound => "Fant ikkje sida",
+ var _ => "Uventa feil"
+ };
+}
+<section class="container py-3 py-lg-5">
+ @switch (Model.ErrorStatusCode) {
+ case HttpStatusCode.NotFound:
+ <div class="text-component text-center margin-bottom-lg">
+ <h1>Fant ikkje siden</h1>
+ <p>Beklagar, sida du prøvar å nå finnes ikkje.</p>
+ <p><a href="/">Gå til forsida</a> eller <a href="/kontakt">kontakt oss</a>.</p>
+ </div>
+ break;
+ case HttpStatusCode.InternalServerError:
+ <div class="text-component text-center margin-bottom-lg">
+ <h1>Her gjekk noko gale</h1>
+ <p>Vi jobbar med å løysa problemet, ver vennleg og prøv igjen seinare.</p>
+ </div>
+ break;
+ default:
+ <div class="text-component text-center margin-bottom-lg">
+ <h1>Heisann, her gjekk ikkje alt etter planen</h1>
+ <p>Ver vennleg og prøv igjen snart.</p>
+ <p><a href="/">Gå til forsida</a> eller <a href="/kontakt">kontakt oss</a>.</p>
+ </div>
+ break;
+ }
+</section>
diff --git a/src/Pages/Errors/Index.cshtml.cs b/src/Pages/Errors/Index.cshtml.cs
new file mode 100644
index 0000000..05e405d
--- /dev/null
+++ b/src/Pages/Errors/Index.cshtml.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Net;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+
+namespace VSH.Pages.Errors;
+
+public class Index : PageModel
+{
+ public HttpStatusCode ErrorStatusCode { get; set; }
+
+ public void OnGet() {
+ try {
+ if (int.TryParse(RouteData.Values["code"]?.ToString(), out var status))
+ ErrorStatusCode = (HttpStatusCode)status;
+ } catch (Exception e) {
+ Console.WriteLine(e);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Pages/Handlekorg.cshtml b/src/Pages/Handlekorg.cshtml
new file mode 100644
index 0000000..9f8f159
--- /dev/null
+++ b/src/Pages/Handlekorg.cshtml
@@ -0,0 +1,100 @@
+@page
+@model VSH.Pages.Handlekorg
+@{
+ ViewData["Title"] = "Handlekorg";
+}
+
+<div class="container py-3 py-md-5">
+ <div class="row">
+ <div class="alert alert-info p-3 d-none" id="order-alert"></div>
+ <div class="col-12 col-lg-8 pe-lg-5">
+ <div class="spinner-border text-primary m-0-auto d-flex" role="status" id="order-summary-spinner">
+ <span class="visually-hidden">Lastar...</span>
+ </div>
+ <div class="d-none" id="order-summary-wrapper">
+ <div class="row">
+ <table class="table">
+ <thead>
+ <tr>
+ <th scope="col">Produkt</th>
+ <th scope="col">Antall</th>
+ <th scope="col">Pris</th>
+ <th scope="col">Totalsum</th>
+ </tr>
+ </thead>
+ <tbody></tbody>
+ </table>
+ </div>
+ <div class="row d-flex float-right flex-column" id="total-wrapper">
+ <div class="d-flex flex-column w-max-content">
+ <span class="fs-3">Totalt inkl. MVA: <span id="total-sum"></span></span>
+ <span>Av dei MVA: <span id="total-tax"></span></span>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="col-12 col-lg-4" id="submit-order-wrapper">
+ <form id="submit-order-form" onsubmit="return false">
+ <div class="loader">
+ <div class="spinner-border" role="status">
+ <span class="visually-hidden">Lastar...</span>
+ </div>
+ </div>
+ <fieldset class="py-3">
+ <div class="mb-3">
+ <label for="input-name" class="form-label">Namn <span class="text-danger">&midast;</span></label>
+ <input type="text" id="input-name" class="form-control" required>
+ </div>
+ <div class="row mb-3">
+ <div class="col">
+ <label for="input-phone" class="form-label">Telefon <span class="text-danger">&midast;</span></label>
+ <input type="tel" inputmode="tel" id="input-phone" class="form-control" required>
+ </div>
+ <div class="col">
+ <label for="input-email" class="form-label">E-postadresse <span class="text-danger">&midast;</span></label>
+ <input type="email" inputmode="email" id="input-email" class="form-control" required>
+ </div>
+ </div>
+ <label for="input-comment" class="form-label">Anna informasjon</label>
+ <textarea class="form-control" id="input-comment" rows="3"></textarea>
+ </fieldset>
+ <ul id="form-errors" class="alert alert-danger py-3 ps-5 d-none"></ul>
+ <fieldset class="py-3">
+ <legend>Betal med</legend>
+ <div class="nav nav-pills nav-fill" role="tablist">
+ <a class="nav-link active" id="vipps-tab-buttom" data-bs-toggle="tab" href="#vipps-tab" role="tab" aria-controls="vipps-tab" aria-selected="true">Vipps</a>
+ <a class="nav-link ms-sm-0 ms-md-2" id="invoice-tab-buttom" data-bs-toggle="tab" href="#invoice-tab" role="tab" aria-controls="invoice-tab" aria-selected="false">Faktura på mail</a>
+ </div>
+ <div class="tab-content">
+ <div class="tab-pane py-3 active" id="vipps-tab" role="tabpanel">
+ <p>Gå til vipps for å fullføre betalinga</p>
+ <div class="form-check mb-3">
+ <input class="form-check-input" type="checkbox" value="" id="vipps-terms-confirm" required>
+ <label class="form-check-label" for="vipps-terms-confirm">
+ Eg samtykker til <a href="/vilkår">salsvilkårane</a> og <a href="/personvern">personvernerklæringa.</a>
+ </label>
+ </div>
+ <div class="d-flex justify-content-end">
+ <button class="btn btn-link shadow-none submit-vipps">
+ <img src="/assets/profile/vipps_button.png" alt="Fortsett med vipps">
+ </button>
+ </div>
+ </div>
+ <div class="tab-pane py-3" id="invoice-tab" role="tabpanel">
+ <p>Du får tilsendt faktura på mail til <span id="invoice-mail">e-postadressa di</span></p>
+ <div class="form-check mb-3">
+ <input class="form-check-input" type="checkbox" id="invoice-terms-confirm" required>
+ <label class="form-check-label" for="invoice-terms-confirm">
+ Eg samtykker til <a href="/vilkår">salsvilkårane</a> og <a href="/personvern">personvernerklæringa.</a>
+ </label>
+ </div>
+ <div class="d-flex justify-content-end">
+ <button class="btn btn-primary btn-lg shadow-none submit-invoice">Send bestilling</button>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/src/Pages/Handlekorg.cshtml.cs b/src/Pages/Handlekorg.cshtml.cs
new file mode 100644
index 0000000..02f72a7
--- /dev/null
+++ b/src/Pages/Handlekorg.cshtml.cs
@@ -0,0 +1,8 @@
+using Microsoft.AspNetCore.Mvc.RazorPages;
+
+namespace VSH.Pages;
+
+public class Handlekorg : PageModel
+{
+ public void OnGet() { }
+} \ No newline at end of file
diff --git a/src/Pages/Index.cshtml b/src/Pages/Index.cshtml
new file mode 100644
index 0000000..aa23602
--- /dev/null
+++ b/src/Pages/Index.cshtml
@@ -0,0 +1,41 @@
+@page
+@using Microsoft.Extensions.Localization
+@inject IStringLocalizer<SharedPageResources> Localizer;
+@model IndexModel
+@{
+ ViewData["Title"] = Localizer["Forsida"];
+}
+
+@section Head {
+ <style>
+ #body-wrapper {
+ overflow-x: hidden;
+ }
+ </style>
+}
+
+<div class="my-2" id="frontpage-image">
+ <svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1283 471.46">
+ <defs>
+ <style>.cls-12,.cls-14,.cls-15,.cls-16,.cls-17,.cls-2,.cls-8,.cls-9{fill:none;stroke:#ee741e;stroke-miterlimit:10}.cls-2{stroke-width:.93px}.cls-8,.cls-9{stroke-width:.94px}.cls-12,.cls-14,.cls-15{stroke-width:.95px}.cls-16{stroke-width:.98px}.cls-17{stroke-width:1px}.cls-18{fill:#ee741e}</style>
+ </defs><path fill="#fff" d="M0 0h1283v471.46H0z"/><path class="cls-2" d="M561.56 286.96l394.6-2.79M561.56 295.34l395.53-.93M235.82 418.65v6.52l155.42 4.65v-6.58l-155.42-4.59zM325.16 396.32l-89.34 22.33M391.24 422.96l89.81-34.55M391.71 429.36l72.59-28.85M464.72 396.32v7.83h63.77v-7l-63.77-.83zM482.91 383.75v8.71M392.17 387.48l88.49.63"/><path class="cls-2" d="M351.91 375.61v-3.38l24.2-3.37v2.44l25.45.35a.12.12 0 010 .23L378 382.82l-33.5-4.65c-.16 0-.16-.9 0-.93l31.64-5.94" transform="translate(1.64)"/><path class="cls-2" d="M326.56 350.25v46.07h5.06v-2.31l9.83 1.84v3.72l3.72.93 8.38-2.79V379.31"/><path stroke-width=".89" stroke-miterlimit="10" stroke="#ee741e" fill="none" d="M340.99 369.79l-9.31-1.86v19.28l9.31 2.54v-19.96z"/><path class="cls-2" d="M347.86 367.93l33.83-4.65s4.66-17.68-11.16-16.75-22.07 3.47-22.67 12 0 9.4 0 9.4z" transform="translate(1.64)"/><path class="cls-2" d="M352.45 365.14l25.5-3.51s3.51-13.33-8.42-12.63-16.63 2.62-17.08 9 0 7.14 0 7.14zM358.43 322.33V340s-25.13-3.72-37.23 7.45l20.47 3.79s17.49-17.82 44.11-4.76" transform="translate(1.64)"/><path class="cls-2" d="M368.82 322.33v19.38"/><path class="cls-2" d="M355.63 314.88h13.54a.41.41 0 00.21-.76c-2.2-1.3-7.52-3.45-14.2.76" transform="translate(1.64)"/><path class="cls-2" d="M360.06 315.81l-1.91 6.52h12.06l-1.77-7.45"/><path class="cls-2" d="M383.55 380s.53 2.27 4 7.18.67 23.53.67 23.53h-5.88s3-15.93.72-21c-1.78-3.6-2.29-3.19-2.29-3.19s1.28 1.89 1.57 7.46a108.72 108.72 0 01-.64 13.94l-4.65.78v-20.29c0-5.59-1.86-1.86-8.38 1.86-7.44 7.44-.93 21.4-.93 21.4s-5.58.93-6.51.93c-3.72-17.68 0-25.12 4.65-27s4.66-3.72 4.66-3.72" transform="translate(1.64)"/><path class="cls-2" d="M339.59 306.51l217.78-.93v1.86l-217.78.98v-1.91zM339.59 306.51l92.14-35.37 129.36-.93"/><path class="cls-2" d="M562.95 217.16l-1.86 85.62h8.38l-4.16 3.73v5.89h-218.1v-3.98M407.53 370.72v-55.04h38.27l-1.06 55.04h-37.21z"/><path class="cls-2" d="M402.41 373.05v-57.37h48.05l-1.34 57.37h-46.71zM547.13 378.17l-151.7-2.79M553.36 312.4v70.5l138.03 3.65M536.22 389.34l151.44 4.65-1.56 2.33 49.96.46-2.16-7.03 18.91.69M535.97 396.32l149.83 4.18.3-4.18"/><path class="cls-2" d="M736.06 396.78l10-.46 2.78 9.36-218.46-7.97"/><path class="cls-2" d="M748.84 405.68v6.88l-218.46-8.33v-6.52l5.59-1.39.25-6.98 10.91-5.23v-5.94l-18.64 6.42v9.66l-49.3-1.93M617.86 264.63h-19.54v-35.37h19.54v35.37zM639.27 264.63H619.72v-35.37h19.55v35.37zM629.7 229.73v34.43M619.72 240.87h19.08M619.87 252.44l18.93.01M608.3 229.73v34.43M598.32 240.87h19.08M598.32 252.44l19.08.01M591.8 224.61l.93 2.79h51.97l1.08-2.79H591.8zM594.33 227.4v39.52h2.88V227.4M640.87 227.4v39.52h2.88V227.4M591.8 266.92h53.98v2.24l-53.98.53v-2.77zM730.77 261.78h-20.32v-35.36h20.32v35.36zM753.02 261.78H732.7v-35.36h20.32v35.36zM743.07 226.88v34.44M732.7 238.03h19.83M732.85 249.59l19.68.02M720.82 226.88v34.44M710.45 238.03h19.83M710.45 249.59l19.83.02M703.68 221.76l.96 2.8h54.02l1.13-2.8h-56.11zM706.31 224.56v39.51h2.99v-39.51M754.68 224.56v39.51h2.99v-39.51M703.68 264.07h56.11v2.24l-56.11.54v-2.78zM858.65 260.7h-22v-36.42h22v36.42zM882.75 260.7h-22v-36.42h22v36.42zM871.98 224.76v35.46M860.75 236.24h21.48M860.92 248.15l21.31.01M847.88 224.76v35.46M836.65 236.24h21.48M836.65 248.15l21.48.01M829.32 219.49l1.05 2.87h58.49l1.23-2.87h-60.77zM832.16 222.36v40.7h3.25v-40.7M884.55 222.36v40.7h3.24v-40.7M829.32 263.06h60.77v2.31l-60.77.55v-2.86zM735.13 314.88h18.61v41.88h-18.61zM744.43 314.88l.35 41.88M735.13 325.28h18.61M735.13 335.31h18.61M735.13 345.13h18.61M755.6 314.88h18.61v41.88H755.6zM764.91 314.88l.35 41.88M755.6 325.28h18.62M755.6 335.31h18.62M755.6 345.13h18.62"/><path class="cls-2" d="M732.34 313.02h44.67v45.6h-44.67zM596.23 314.75h16.39v38.89h-16.39zM604.43 314.75l.3 38.89M596.23 324.41h16.39M596.23 333.72h16.39M596.23 342.84h16.39M614.26 314.75h16.39v38.89h-16.39zM622.46 314.75l.3 38.89M614.26 324.41h16.39M614.26 333.72h16.39M614.26 342.84h16.39"/><path class="cls-2" d="M594.6 313.02h37.69v42.35H594.6zM855.29 317.67h19.63v41.88h-19.63zM865.1 317.67l.36 41.89M855.29 328.08h19.62M855.29 338.11h19.62M855.29 347.92h19.62M876.87 317.67h19.63v41.88h-19.63zM886.69 317.67l.36 41.89M876.87 328.08h19.63M876.87 338.11h19.63M876.87 347.92h19.63"/><path class="cls-2" d="M853.32 315.81h45.14v45.6h-45.14zM696.97 313.95h22.34v49.33h-22.34z"/><path class="cls-2" d="M692.32 310.23h31.64v67.94h-31.64zM692.32 378.17h31.64v8.38h-31.64zM695.06 386.55l-3.67 4.78 27.92-.13-1.63-4.65M730.47 306.51h13.03v4.65h-13.03z"/><circle class="cls-2" cx="722.1" cy="340.01" r=".93"/><path class="cls-2" d="M720.46 342.8v1.87a.93.93 0 01-.93.93h-4.65v-.94h5.58" transform="translate(1.64)"/><path class="cls-2" d="M688.65 386.47v-79.96h39.27v82.43"/><path class="cls-2" d="M751.3 373.52h14.34a.09.09 0 01.08.14c-.9 1.08-6.79 7.51-14.46-.05a.05.05 0 01.04-.09z" transform="translate(1.64)"/><path class="cls-2" d="M765.83 373.52s.23 1.86-.7 18.61c-8.37 4.65-14-1.69-14-1.69v-16.92" transform="translate(1.64)"/><path class="cls-2" d="M385.26 346.49v24.91M345.17 351.18v48.86"/><path class="cls-2" d="M749.31 185.52L904.73 179l79.11 14.89L816 199.48l-294.52 8.37 52-16.7 157.81-4.6" transform="translate(1.64)"/><path stroke-width="1.03" stroke-miterlimit="10" stroke="#ee741e" fill="none" d="M732.8 156.42l17.02.25 1.13 32.57H732.8v-32.82z"/><path class="cls-2" d="M526.66 210.65v4.73l458.82-14.08v-4.27l-458.82 13.62z"/><path class="cls-2" d="M961.16 202.04l24.32 5.81 6.52-13.02-9.64-1.52M522.93 207.85v8.95l3.73 1.57v4.55l18.94-7.53M569.47 302.78l387.16-.93-1.86-99.58"/><path class="cls-2" d="M947.54 301.85c.39.93-.38 94.93-.38 94.93l-182-4.65" transform="translate(1.64)"/><path class="cls-2" d="M939.88 396.78l.93 13.03-165.11-3.43M956.69 288.36l103.93 27.45-2.99 8.6-101.13-28.37M1028.18 316.74l6.63 89.35-49.33 1.78M1031.15 405.84v10.14M562.84 222.36l391.86-9.53M561.56 275.79l394.07-2.47M562.68 229.73l31.45-.47M643.75 229.26l62.99-.93M757.67 226.88l73.91-2.12M887.79 224.28l66.91-1.92M562.68 239.03l31.45-.46M643.75 238.57l62.99-.93M757.67 236.19l73.91-2.12M887.79 233.59l66.91-1.92M562.68 250.2l31.45-.46M643.75 249.74l62.99-.94M757.67 247.36l73.91-2.13M887.79 244.76l66.91-1.92M562.68 260.44l31.45-.47M643.75 259.97l62.99-.93M757.67 257.6l73.91-2.13M887.79 254.99l66.91-1.91"/><path stroke-width=".92" stroke-miterlimit="10" stroke="#ee741e" fill="none" d="M561.75 268.81l30.52-.46M645.32 268.35l184.27-2.79"/><path stroke-width=".91" stroke-miterlimit="10" stroke="#ee741e" fill="none" d="M890.09 263.37l64.61-1.92"/><path class="cls-2" d="M574.06 302.78v80.62M580.32 302.78v80.47M587.43 302.74v80.66M559.84 312.56v70.69M566.96 305.11v78.29M634.55 302.78l.06 82.37M640.81 302.78v82.37M647.93 302.74v82.41M655.03 302.78v83.3M661.29 302.78v83.3M668.4 302.74v83.34M674.57 302.78v83.3M680.83 302.78v83.3M594.53 355.38v28.84M600.79 355.38v28.78M607.91 355.37v28.85M615.01 355.38v28.84M621.27 355.38v28.78M628.1 355.37v29.78M594.53 302.75v9.81M600.79 302.75v9.79M607.91 302.74v9.82M615.01 302.75v9.81M621.27 302.75v9.79M628.38 302.74v9.82M802.07 301.86v90.73"/><path class="cls-8" d="M808.33 301.86v91.49M815.45 301.81v91.72M822.55 301.86v91.67"/><path class="cls-9" d="M828.81 301.86v91.67"/><path class="cls-8" d="M835.92 301.81v91.72"/><path stroke-width=".94" stroke-miterlimit="10" stroke="#ee741e" fill="none" d="M842.09 301.86v91.67"/><path class="cls-9" d="M848.35 301.86v91.67"/><path class="cls-2" d="M855.47 301.81v13.54M780.67 302.32v90.27M787.86 302.32v90.11M794.97 302.32v90.27M755.54 358.16v14.89M762.73 358.18v14.87M769.84 359.09v32.57M775.08 359.11v33.48M734.14 359.09v30.71M741.33 359.09v30.66M748.44 358.16v31.64M757.4 302.32v10.24M764.59 302.32v10.24M771.71 302.62v10.57M736 302.62v3.42M743.19 302.62v4.35M750.3 302.32v10.26M882.11 301.82v13.53M888.37 301.82v13.5M895.49 301.81v13.54M902.59 301.86v93.53M908.85 301.86v93.35M915.96 301.81v93.58M922.13 301.86v94.46M928.39 301.86v94.28M935.51 301.81v94.51M943.88 301.81v94.51M861.64 301.96v13.39M867.9 301.96v13.36M875.01 301.95v13.4"/><path stroke-width=".95" stroke-miterlimit="10" stroke="#ee741e" fill="none" d="M855.47 360.95v33.51"/><path class="cls-12" d="M882.11 361.9v33.49"/><path stroke-width=".95" stroke-miterlimit="10" stroke="#ee741e" fill="none" d="M888.37 361.88v33.45"/><path class="cls-12" d="M895.49 361.88v33.51"/><path class="cls-14" d="M861.64 360.97v33.49M867.9 360.97v33.42M875.01 360.95v33.51"/><path class="cls-2" d="M516.82 364.18v-7.39s3.72-4.71 7.45-4.71 6.51 2.79 5.58 4.66-.93 7.44-.93 7.44a15.35 15.35 0 01-12.1 0z" transform="translate(1.64)"/><path class="cls-2" d="M516.82 365.42V377s6.52 2.09 12.1.23v-13M523.43 363s2.7.3 2.7-.63-1.68-2.49-2.7-1.71 0 2.34 0 2.34z" transform="translate(1.64)"/><path class="cls-15" d="M407.53 358.53h37.44M374.65 313.02v29.24M382.56 312.4v32.03M390.91 312.56v58.9M399.29 312.56v58.9"/><path class="cls-2" d="M454.99 312.09l-1.72 63.75M463.37 313.02l-1.73 63.75"/><path class="cls-16" d="M480.12 313.02l-1.72 63.75M471.75 313.02l-1.73 63.75M489.43 313.02l-1.73 63.75"/><path class="cls-17" d="M497.81 312.56l-1.73 65.14M514.56 312.56l-1.73 65.14M506.18 312.56l-1.73 65.14"/><path class="cls-2" d="M521.7 312.4v41.24M530.38 312.4l-.5 40.88M537.35 312.4l-1.13 65.3M545.89 312.09l-1.71 66.02M552.01 312.4v70.85l1.99-.33M960.96 297.29l1.25 87.86M975.68 301.42l-.44 93.04M990.45 305.56v102.31M1004.09 309.3l1.87 98.19M1016.51 313.01l3.41 94.01"/><path class="cls-2" d="M946 414.88q-3.35-10.53-6.36-21.17c4.91 5.55 5.88 13.66 10.36 19.56l-3.44-19.6a3.29 3.29 0 01.27-2.59c1.35 1.32 1.7 3.33 2.06 5.18a82.64 82.64 0 004.21 14.63 3 3 0 001.51 1.94c1.26-7.83-.92-15.83-.32-23.74.55 7.4 1.13 14.89 3.38 22a6.86 6.86 0 00.91-2.43l3-12.65a142 142 0 01-1.91 16.43l5.72-13c.82 4.36-1.47 8.78-1.09 13.21 1.13-1 1.53-2.57 2-4a25.27 25.27 0 014.37-8L967.14 415q4.1-5.27 8.52-10.26c.77 3.36-2 6.57-2 10l6.72-7.18c.75 1.66-.51 3.5-.8 5.3a1.58 1.58 0 000 .78c.35.94 1.73.7 2.68.35a13 13 0 016.58-.85c1.41.23 2.76.77 4.16 1.05a5.59 5.59 0 004.16-.49M944.75 412.93c-1.78-1.88-2.28-4.64-3.82-6.73-.41-.56-1.08-1.11-1.73-.85s-.73 1.14-.71 1.85l.08 2.86c0 .54 0 1.17-.48 1.45a1.19 1.19 0 01-.79.1 6.29 6.29 0 01-1.59-.66 2.57 2.57 0 00-1.66-.32 1.12 1.12 0 00-.9 1.26 1.54 1.54 0 001.14.86 14.76 14.76 0 005.18.22c-1.48.42-3.07.25-4.56.61a30.28 30.28 0 00-2.93 1.09c-2.94 1-6.17.74-9.27.44" transform="translate(1.64)"/><path class="cls-2" d="M947.83 414.31a33.48 33.48 0 01-1.49-6.59l-1.42-9.13c.32 0 .56.29.73.58a25.08 25.08 0 012.5 5.16c.41 1.35.59 2.77 1 4.11.54 1.66 1.48 3.2 1.73 4.93.29-5.67.6-11.35 1.38-17q1.37 5.67 2.47 11.4c.35 1.82.73 3.74 2 5.1 2-4.4 2.17-9.35 2.35-14.17.29 2.29.2 4.62.33 6.92a14.84 14.84 0 001.68 6.66 27.13 27.13 0 003.15-9.25l-.47 7.9a9.64 9.64 0 00.09 2.63 3.53 3.53 0 001.77-1.76c1.25-2.22 2-4.8 3.77-6.6a59.09 59.09 0 00-1.52 9.25 6.7 6.7 0 002-2.44q1.43-2.43 2.82-4.87a55.44 55.44 0 01-1 7.48M977.47 408.1a30.9 30.9 0 004.12-7.81c.46.54.94 1.06 1.45 1.55a2.82 2.82 0 001.11.74 1.67 1.67 0 001.89-1.21 2.37 2.37 0 00-.73-2.25 4.14 4.14 0 00-2.23-1 5.93 5.93 0 002.69-1.92 2 2 0 00-.55-2.91 2.22 2.22 0 00-2.24.53 4.05 4.05 0 00-1.4 2.76 3.16 3.16 0 00-1.69-1.44 2.62 2.62 0 00-2.58 1.51 2.39 2.39 0 00-.41 1.36 2 2 0 001.59 1.59 5.74 5.74 0 002.4-.14" transform="translate(1.64)"/><path class="cls-2" d="M971.64 406.82a43.28 43.28 0 003.46-8.65 4.59 4.59 0 01.75-1.93c.22-.26.49-.46.72-.7a2.81 2.81 0 00.78-2 1.32 1.32 0 00-.14-.65c-.4-.65-1.4-.42-2 0a5.88 5.88 0 00-2 2.5 3.57 3.57 0 00-2.72-1.69 1.63 1.63 0 00-1.62.65c-.39.71.16 1.59.81 2.07a4.73 4.73 0 003.82.81" transform="translate(1.64)"/><path class="cls-2" d="M963.59 401.9c.53-2.47 2.15-4.58 2.73-7a22.71 22.71 0 01.71-3.17c.31-.76.83-1.57.56-2.35a1.6 1.6 0 00-2.39-.56 2.69 2.69 0 00-.88 2.57 2.07 2.07 0 00-2.62-.2 1.6 1.6 0 000 2.46c.83.56 1.94.07 2.82-.42l3.11-1.75a4.1 4.1 0 011.33-.56 1.39 1.39 0 011.31.43c.54.7 0 1.71-.7 2.25a3 3 0 01-2 .72A1.76 1.76 0 01966 393M959 400.58l.28-10a2.13 2.13 0 002.34-1.35 6.17 6.17 0 00.29-2.9 2.41 2.41 0 00-.22-1 .83.83 0 00-.86-.46 1.07 1.07 0 00-.53.41 5.66 5.66 0 00-.66 3.71 6.35 6.35 0 00-2.21-3.3c-.3-.22-.74-.41-1-.15a.81.81 0 00-.13.63 6 6 0 001.75 3.57 1.37 1.37 0 00-1.49-1.16 2.6 2.6 0 00-1.75 1.07 1 1 0 00-.27.94 1 1 0 00.73.48 6.5 6.5 0 003.19 0M749.35 407.26q-1.61-3.75-2.83-7.64a17.35 17.35 0 012.34 6.77c.72-2.11.18-4.69 1.58-6.43l.29 7.35a19.69 19.69 0 013-5.28 6.47 6.47 0 01-1.31 2.32 3.32 3.32 0 00-.77 2.49 27.28 27.28 0 015.82-2.08l-1.28 2.39a4.22 4.22 0 011.4-1.64 1.47 1.47 0 012 .31c.11.18.16.38.28.55.4.59 1.31.48 1.93.13a6.34 6.34 0 011.85-1c.89-.18 1.75.37 2.66.49 1.25.18 2.51-.47 3.77-.31.76.1 1.46.49 2.22.65 1.93.39 3.9-.78 5.86-.55a19.88 19.88 0 012.71.77 14.72 14.72 0 003 .38l5.11.29" transform="translate(1.64)"/><path class="cls-2" d="M780.12 407.83c-1.9-.75-4-.4-6.06-.51a29.3 29.3 0 00-3.37-.2 18.26 18.26 0 00-4.33 1.11 26.24 26.24 0 01-4.87 1M749.51 404.89a26.24 26.24 0 01-.52-7.29 2.83 2.83 0 01.9-2.22c1.15-.78 3 .28 4-.65a1.56 1.56 0 000-2.2 2.12 2.12 0 00-2.3-.33 3.49 3.49 0 00-1.68 1.75 7.58 7.58 0 00-.31-2.68 3.26 3.26 0 00-.81-1.48 1.58 1.58 0 00-1.56-.44 2 2 0 00-1 2.27 4.37 4.37 0 002.12 3.1 5.29 5.29 0 00-3.34-1.07 2.68 2.68 0 00-1.92.73 1.39 1.39 0 00-.07 1.89 2 2 0 001.35.42 11.89 11.89 0 003.36-.39M458.36 408.52a15.77 15.77 0 003.21-8.77 37.41 37.41 0 01-3.36 6.19l-.72-2.9c-.89 1-.64 3-1.88 3.52-1 .48-2.58-.37-3.27.54-.5.65-.12 1.09-.92 1.25-.41.08-1.62-.74-2-.92l-4-1.85c-.48-.22-1.05-.64-.88-1.14a.84.84 0 01.4-.43c1.17-.67 2.62.11 3.69.93s2.33 1.76 3.63 1.4a.75.75 0 00.35-.19.92.92 0 00.13-.7 12.83 12.83 0 01.54-4.69c.78 2.07.48 6.29-1.26 7.9s-5.39 2-7.44 2.76l-6.69 2.37a31.42 31.42 0 01-4.74 1.4M280 432.39c-2.64-1.48-5.84-1.64-8.86-1.36s-6 1-9 1.09c-5.8.2-11.55-1.81-17.34-1.36a38.31 38.31 0 005.2-5.86l-5.31 5.16a17 17 0 01-.64-4.85q-.19 2.55-.6 5.07l-2.78-3.41.82 4.41c-2.08-.84-2.37-4.53-4.62-4.53l1.58 4.85a10.65 10.65 0 01-2.43-3.26c-.48.45-.45 1.21-.69 1.81s-1.23 1-1.49.41a1.37 1.37 0 010-.67c.09-1.3-1-2.33-1.6-3.48a10.37 10.37 0 01-.91-3.94l-.84-8.84c-1.54 5.31 1.21 11 .6 16.46a57.61 57.61 0 00-7.24-11.28c-.44-.54-1.15-1.11-1.74-.75.07 1.62 1.23 2.95 2.33 4.13q4.26 4.53 8.74 8.84a42.88 42.88 0 00-13.46-7.47 67.92 67.92 0 0010.92 9 37 37 0 00-7.24-3.05 12.59 12.59 0 00-7.73.19 92.59 92.59 0 0017.24 2.07c0 .73-.77 1.19-1.45 1.45-5.14 1.94-10.88 1.41-16.23 2.67a48.81 48.81 0 00-8.16 2.95M286 310.43h16.58a6.28 6.28 0 001.63-.21c2.61-.68 9.65-3.19 2-9a19.15 19.15 0 00-17.4-3.23c-3.95 1.18-7 3.41-8.27 5.38-1.47 2.3-1 3.06-.63 4.13s2.55 2.6 6.31 2.92M288.64 286.67s3.06 1.76 1 3.73c-1.17 1.1-1.74 3 .13 4.24M293.54 286.26s3.06 1.76 1 3.73c-1.17 1.1-1.74 3 .13 4.24M298 285.89s3.06 1.76 1 3.73c-1.17 1.1-1.74 3 .13 4.24M289.33 298.21a3.74 3.74 0 00-1.41 4.21M295.48 297.17s-3.65 1.81-2.71 5.25M300.67 298s-3.13 1.35-2.58 4.4M352.84 77.37V85l20.25-8.78v-8c-4.46-4.15-13.71-3.19-13.71-3.19l-6.54 12.28 20.09-8.93" transform="translate(1.64)"/><ellipse class="cls-2" cx="367.39" cy="67.8" rx="1.43" ry=".64"/><ellipse class="cls-2" cx="366.09" cy="75.88" rx="1.59" ry="1.43"/><ellipse class="cls-2" cx="359.58" cy="72.74" rx="1.28" ry=".48"/><path class="cls-2" d="M435.69 33.88s0 1.31-1.31 0 1.31-3.88 2.62-2.61l1.31 1.3M463.78 33.23l-6.62-2.32s-7.76-1.6-14.54 0-6.28 7.54-5 8.85l2.22 2.24c-1.73 3.5.42 7 .42 7h3.92a5.73 5.73 0 01-1.31-4 2.56 2.56 0 012.61-2.62l1.31 1.31c1.31 1.31 7.84 0 7.84 0-1.31 2.61 2.61 5.23 2.61 5.23h2.62c-1.31-1.31-1.31-9.15.74-6.54s6.87 0 6.87 0l1.53-2.62c-2.61 0-3.92-3.92-3.92-3.92" transform="translate(1.64)"/><path class="cls-2" d="M463.36 37.53s-2.44-3.51 2.71-5.45l1.52.32s-.59 2.88-2.11 2.6M564.42 35a2.56 2.56 0 01-2.62-2.61c0-1.31 1.31-2.61 3.27.65h1.31c1.3 0 1.3 0 3.91 1.84s0 3.39 0 3.39a11.48 11.48 0 00-3.91.65c-1.31.65.17 4.06-.66 6.53-.65 2-3.26 3.27-3.26 3.27s-1 5.88-.31 7.19c1 .65 1.31 3.26 1.31 3.26h-3.62v-2.64a1.28 1.28 0 01-1.3-1.31c0-1.3-1.15-5.88-1.47-5.88-4.09 2-10.29-.65-10.29-.65" transform="translate(1.64)"/><path class="cls-2" d="M546.78 49l-2 3v2.61a4.58 4.58 0 011.3 2.61 5.24 5.24 0 00.29 2l-2.9-.65s0-2.61-1.31-2.61v-2.7L540.9 52l1.3-2.62s.71-3.35-.3-4.94a4.75 4.75 0 012.92-6.81c2.48-.83 11.76 1.3 14.37 0S561.8 35 561.8 35" transform="translate(1.64)"/><rect class="cls-2" x="625.42" y="67.29" width="5.69" height="1.81" rx=".62"/><path class="cls-2" d="M623.31 76.87a2.19 2.19 0 00-2 2.17v14a2.19 2.19 0 002.18 2.18h6.26a2.19 2.19 0 002.18-2.18V79a2.19 2.19 0 00-1.57-2" transform="translate(1.64)"/><path class="cls-2" d="M633.58 93.17v-.11M626.23 69.1l-1.52 7.76M630.41 69.1l1.51 7.74.01.02M631.92 76.84l.12.12M625.47 72.98l5.31-1.98M622.96 81.68h10.63M622.96 91.93h10.62M630.48 65.22v-2.85M632.55 65.82l2.21-2M633.33 67.61l3.1.15"/><path class="cls-2" d="M654.59 155.68s3.63 5.23 8.59 2.35a3.63 3.63 0 01-2.67 4.69s-5.73-1.81-6.49-6.49-.38-12.27 9.92-14.07a17.64 17.64 0 018.33.25h.14a10.27 10.27 0 015.66 4.4c.76 1.08 1.91 5.77 1.91 5.77s-6.49 3.61-13.36.36c-7.26-2.49-8.78-3.21-12.03 2.74zM672.27 142.41s-6.37 2.91-2.58 11.61" transform="translate(1.64)"/><path class="cls-2" d="M664.15 142.12a19 19 0 00-2.09-2l-1.44-1.12s6.62-1.32 8.2 2.77" transform="translate(1.64)"/><ellipse class="cls-2" cx="676.08" cy="147.75" rx=".76" ry=".72"/><path class="cls-2" d="M275.58 202.46l.16 2.55 14.45-.72-.18-2.75-14.16.9-.27.02zM274.09 227.75l6.32 1.66-.94-14.66-3.73-9.74-1.89 8.26.24 14.48z"/><path class="cls-2" d="M274.09 227.75l3.3-2.28 2.77 3.88M276.65 213.78l.74 11.69M279.45 214.52l13.86-.89-2.92-9.36"/><path class="cls-2" d="M280.41 229.41l14.39-1.6-1.49-14.18M280.93 202.12l.17 2.55 2.84 4.5 3.44-.22-2.37-4.68.08-2.42M280.25 226.99l14.26-1.89"/><path class="cls-2" d="M284.91 218.44a2.89 2.89 0 00-3.18-.13 2.45 2.45 0 102.33 4.22 3.11 3.11 0 001.49-1.75" transform="translate(1.64)"/><ellipse class="cls-2" cx="287.66" cy="219.43" rx="2.41" ry="2.86" transform="rotate(-48.66 288.45921753 217.6128333)"/><path class="cls-2" d="M287.32 217.37l4.13 3.95M282.03 221.8l4.64-3.24"/><path class="cls-2" d="M304.82 114.56s3 1.25.9 2.75c-1.19.85-1.8 2.29 0 3.15M309.27 114.19s3 1.25.9 2.75c-1.19.85-1.8 2.29 0 3.15" transform="translate(1.64)"/><path class="cls-2" d="M302.55 124.63h12.66a.65.65 0 01.65.65v2.45h-14v-2.45a.65.65 0 01.69-.65zM303.59 123.08h10.28a.53.53 0 01.53.53v1h-11.34v-1a.53.53 0 01.53-.53z"/><path class="cls-2" d="M300.75 127.73l.28 2.52 1.36 12a.5.5 0 00.49.44h8.61a.5.5 0 00.49-.44l1.7-14.54" transform="translate(1.64)"/><path class="cls-2" d="M315.03 130.26h-12.36M303.42 136.91h10.83"/><path class="cls-18" d="M394.18 150.93h1.24l3.43 10.23 3.43-10.23h1.24l-4.12 11.9h-1.1zM405.32 150.93h1.18v11.9h-1.18zm.81 0H413V152h-6.83zm0 5.44h5.93v1.1h-5.93zm0 5.36H413v1.1h-6.83zM415.33 150.93h1.18v11.9h-1.18zm.84 10.8H423v1.1h-6.8zM424.94 150.93h1.17v11.9h-1.17zm.57 8.27l6.52-8.27h1.52l-7.55 9.18zm3.35-2.72l.68-1.22 4.51 7.57h-1.41zM436.86 162.44a3.43 3.43 0 01-1.42-1.5 5.25 5.25 0 01-.49-2.37v-3.37a5.26 5.26 0 01.49-2.38 3.36 3.36 0 011.42-1.49 5.19 5.19 0 014.53 0 3.43 3.43 0 011.43 1.49 5.4 5.4 0 01.49 2.38v3.37a5.38 5.38 0 01-.49 2.37 3.51 3.51 0 01-1.43 1.5 5.28 5.28 0 01-4.53 0zm3.89-1a2.5 2.5 0 001-1.1 4 4 0 00.35-1.75v-3.48a4 4 0 00-.35-1.75 2.5 2.5 0 00-1-1.1 3.66 3.66 0 00-3.25 0 2.42 2.42 0 00-1 1.1 3.9 3.9 0 00-.36 1.75v3.48a3.87 3.87 0 00.36 1.75 2.42 2.42 0 001 1.1 3.66 3.66 0 003.25 0zM454.72 150.93H456v11.9h-1.18v-10.22l.13.52-3.59 8.05h-.83l-3.58-7.88.12-.69v10.22h-1.18v-11.9h1.24l3.82 8.59zM467.77 150.93H469v11.9h-1.18v-10.22l.12.52-3.58 8.05h-.84L460 153.3l.12-.69v10.22h-1.22v-11.9h1.23l3.82 8.59zM472 150.93h1.18v11.9H472zm.81 0h6.83V152h-6.83zm0 5.44h5.93v1.1h-5.93zm0 5.36h6.83v1.1h-6.83zM482 150.93h1.19l6.9 10.72-.48-.33v-10.39h1.18v11.89h-1.2L482.5 152l.64.47v10.33H482zM493.82 161.49h1.34v1.34h-1.34zm.08-10.56h1.17v9.17h-1.17zM394.91 180.47h.79v7.92h-.79zm.55 0h4.44v.73h-4.44zm0 3.69h3.84v.73h-3.84zM401.27 180.46h.78v7.93h-.78zm.48 3.85h2.71a1.67 1.67 0 00.78-.19 1.35 1.35 0 00.51-.55 1.68 1.68 0 00.19-.82 1.8 1.8 0 00-.18-.82 1.38 1.38 0 00-.52-.55 1.61 1.61 0 00-.78-.19h-2.71v-.73h2.66a2.46 2.46 0 011.21.28 2 2 0 01.81.81 2.48 2.48 0 01.29 1.2 2.45 2.45 0 01-.29 1.2 2 2 0 01-.81.81 2.49 2.49 0 01-1.21.28h-2.66zm2.54.49l.73-.26 2 3.85h-.94zM408.55 180.47h.78v7.92h-.78zm.54 0h4.55v.73h-4.55zm0 3.62h4v.73h-4zm0 3.57h4.55v.73h-4.55zM415.22 180.47h.78v7.92h-.79zm.76 7.19h1.79a2.36 2.36 0 001.65-.51 2.06 2.06 0 00.55-1.55v-2.34a2.06 2.06 0 00-.55-1.55 2.36 2.36 0 00-1.65-.51H416v-.73h1.76a4 4 0 011.68.31 2.1 2.1 0 011 .95 3.36 3.36 0 01.33 1.58v2.24a3.36 3.36 0 01-.33 1.58 2.17 2.17 0 01-1 1 4 4 0 01-1.68.31H416zM424.38 180.47h.95l2.93 7.92h-.88l-2.52-7.1-2.53 7.1h-.87zm-1.57 5.27H427v.73h-4.17zM434.44 184.34v1.17a3.83 3.83 0 01-.31 1.65 2.06 2.06 0 01-.92 1 3.26 3.26 0 01-1.55.33 3.47 3.47 0 01-1.56-.32 2 2 0 01-.93-.92 3.44 3.44 0 01-.31-1.56v-2.34a3.91 3.91 0 01.3-1.64 2.13 2.13 0 01.93-1 3.22 3.22 0 011.54-.33 3 3 0 011.33.27 2.21 2.21 0 01.91.78 3.55 3.55 0 01.5 1.31h-.85a2.72 2.72 0 00-.39-.91 1.63 1.63 0 00-.63-.54 2 2 0 00-.87-.18 2.33 2.33 0 00-1.11.25 1.64 1.64 0 00-.66.74 3 3 0 00-.22 1.24v2.34a2.71 2.71 0 00.22 1.15 1.51 1.51 0 00.68.69 2.48 2.48 0 001.12.22 2.2 2.2 0 001.09-.23 1.52 1.52 0 00.65-.72 3.25 3.25 0 00.21-1.26v-.46h-1.92v-.73zM441 188.39h-.79v-7.26l-1.45.91v-.82l1.13-.75H441zM442.67 187.76l3-3.91a3.37 3.37 0 00.46-.75 1.76 1.76 0 00.16-.65 1.27 1.27 0 00-.37-1 1.43 1.43 0 00-1-.35 1.41 1.41 0 00-1 .38 1.71 1.71 0 00-.47 1h-.82a3.11 3.11 0 01.4-1.17 2 2 0 01.78-.73 2.33 2.33 0 011.11-.26 2.64 2.64 0 011.21.25 1.62 1.62 0 01.76.7 2.19 2.19 0 01.27 1.12 2.23 2.23 0 01-.22.85 4.79 4.79 0 01-.6 1l-2.63 3.37h3.49v.73h-4.47zM452.28 185.19v.73h-3.67v-.73zM455.66 188.39h-.78v-7.26l-1.46.91v-.82l1.13-.75h1.11zM460.6 184.46v.19a.74.74 0 01-.45.37 2.26 2.26 0 01-.77.12 2.06 2.06 0 01-1.09-.29 1.89 1.89 0 01-.72-.81 2.8 2.8 0 01-.26-1.22 3.06 3.06 0 01.26-1.31 1.76 1.76 0 01.76-.83 2.61 2.61 0 012.39 0 1.91 1.91 0 01.75.84 3 3 0 01.26 1.33 3.7 3.7 0 01-.11.91 5.1 5.1 0 01-.31 1l-.06.14a1 1 0 00-.07.15l-1.69 3.39h-.88zm0-.49a1.79 1.79 0 00.37-1.2 1.77 1.77 0 00-.38-1.21 1.47 1.47 0 00-2.1 0 1.77 1.77 0 00-.38 1.21 1.73 1.73 0 00.38 1.19 1.51 1.51 0 002.11 0zM394.91 193.87h.79v7.93h-.79zm.56 7.2H400v.73h-4.54zM403.59 193.87h.94l2.93 7.93h-.87l-2.53-7.11-2.52 7.11h-.88zm-1.59 5.27h4.17v.73H402zM409.34 201.56a2.06 2.06 0 01-.92-1 3.61 3.61 0 01-.31-1.61v-5.11h.79V199a2.18 2.18 0 00.49 1.56 2 2 0 001.5.52 2 2 0 001.51-.52 2.18 2.18 0 00.5-1.56v-5.15h.78V199a3.76 3.76 0 01-.3 1.61 2.13 2.13 0 01-.93 1 3.47 3.47 0 01-1.56.32 3.39 3.39 0 01-1.55-.37zM415.43 193.86h.78v7.94h-.78zm.48 3.85h2.71a1.55 1.55 0 00.78-.19 1.29 1.29 0 00.51-.55 1.68 1.68 0 00.19-.82 1.8 1.8 0 00-.18-.82 1.23 1.23 0 00-.52-.54 1.51 1.51 0 00-.78-.2h-2.71v-.73h2.67a2.45 2.45 0 011.2.29 1.89 1.89 0 01.81.8 2.48 2.48 0 01.29 1.2 2.42 2.42 0 01-.29 1.2 2 2 0 01-.81.81 2.47 2.47 0 01-1.2.28h-2.67zm2.55.49l.72-.25 2 3.85h-.94zM422.71 193.87h.78v7.93h-.78zm.75 7.2h1.8a2.36 2.36 0 001.65-.52 2 2 0 00.54-1.55v-2.34a2.06 2.06 0 00-.54-1.55 2.36 2.36 0 00-1.65-.51h-1.8v-.73h1.76a3.91 3.91 0 011.68.31 2.08 2.08 0 011 .95 3.39 3.39 0 01.33 1.58V199a3.24 3.24 0 01-.34 1.58 2.1 2.1 0 01-1 .95 4 4 0 01-1.68.32h-1.76zM431.87 193.87h.95l2.92 7.93h-.87l-2.52-7.11-2.53 7.11H429zm-1.57 5.27h4.17v.73h-4.17zM441.93 197.74v1.17a4 4 0 01-.31 1.65 2.11 2.11 0 01-.92 1 3.29 3.29 0 01-1.55.33 3.61 3.61 0 01-1.56-.31 2.06 2.06 0 01-.94-.93 3.56 3.56 0 01-.31-1.55v-2.34a4 4 0 01.31-1.65 2.08 2.08 0 01.93-1 3.23 3.23 0 011.54-.32 3 3 0 011.32.26 2.09 2.09 0 01.91.78 3.39 3.39 0 01.51 1.31H441a2.87 2.87 0 00-.39-.9 1.63 1.63 0 00-.63-.54 2 2 0 00-.87-.18 2.34 2.34 0 00-1.11.24 1.62 1.62 0 00-.66.75 3 3 0 00-.22 1.24v2.34a2.55 2.55 0 00.22 1.14 1.47 1.47 0 00.68.69 2.45 2.45 0 001.12.23 2.23 2.23 0 001.09-.24 1.42 1.42 0 00.64-.72 3.06 3.06 0 00.22-1.26v-.46h-1.92v-.73zM448.48 201.8h-.79v-7.27l-1.45.91v-.82l1.12-.75h1.12zM450.16 201.16l3-3.91a3.31 3.31 0 00.45-.75 1.58 1.58 0 00.16-.65 1.3 1.3 0 00-.36-1 1.44 1.44 0 00-1-.34 1.38 1.38 0 00-1 .37 1.71 1.71 0 00-.47 1.05h-.82a2.85 2.85 0 01.4-1.16 2 2 0 01.78-.74 2.33 2.33 0 011.11-.25 2.81 2.81 0 011.21.24 1.67 1.67 0 01.76.7 2.21 2.21 0 01.26 1.12 2.19 2.19 0 01-.21.85 5.5 5.5 0 01-.6 1l-2.63 3.38h3.49v.73h-4.47zM459.76 198.59v.73h-3.66v-.73zM463.15 201.8h-.78v-7.27l-1.46.91v-.82l1.13-.75h1.11zM469.05 194.53L467 201.8h-.86l2.09-7.2h-2.71v1.46h-.79v-2.19h4.32zM396.21 215.17a3.68 3.68 0 01-.95-.33 3.75 3.75 0 01-.84-.54l.48-.62a3.47 3.47 0 001.09.65 3.71 3.71 0 001.31.22 2.67 2.67 0 001.58-.41 1.3 1.3 0 00.56-1.13 1 1 0 00-.25-.72 1.5 1.5 0 00-.62-.41 7.84 7.84 0 00-1-.25h-.24a8.26 8.26 0 01-1.33-.33 1.94 1.94 0 01-.86-.58 1.75 1.75 0 01-.35-1.15 2.32 2.32 0 01.33-1.26 2.1 2.1 0 011-.79 3.86 3.86 0 011.52-.27 4 4 0 01.84.09 4.28 4.28 0 01.81.27 5 5 0 01.79.47l-.46.61a4.34 4.34 0 00-1-.54 3 3 0 00-1-.17 2.39 2.39 0 00-1.5.41 1.35 1.35 0 00-.54 1.15.93.93 0 00.27.71 1.66 1.66 0 00.66.38 9.36 9.36 0 001.09.26h.18a8.4 8.4 0 011.24.35 2 2 0 01.83.62 1.74 1.74 0 01.33 1.12 2.15 2.15 0 01-.34 1.24 2.1 2.1 0 01-1 .79 4.09 4.09 0 01-1.57.27 5.44 5.44 0 01-1.06-.11zM402.7 215a2.13 2.13 0 01-.93-1 3.75 3.75 0 01-.31-1.61v-5.11h.79v5.15a2.12 2.12 0 00.5 1.56 2 2 0 001.49.52 2 2 0 001.51-.52 2.16 2.16 0 00.5-1.56v-5.15h.75v5.11a3.75 3.75 0 01-.31 1.61 2.13 2.13 0 01-.93 1 3.44 3.44 0 01-1.56.32 3.35 3.35 0 01-1.5-.32zM408.78 207.27h.79l4.61 7.14-.33-.22v-6.92h.79v7.92h-.8l-4.7-7.2.43.31v6.89h-.79zM416.6 207.27h.79v7.93h-.79zm.76 7.2h1.79a2.36 2.36 0 001.65-.52 2 2 0 00.55-1.55v-2.33a2.07 2.07 0 00-.55-1.56 2.36 2.36 0 00-1.65-.51h-1.79v-.73h1.76a4 4 0 011.68.31 2.14 2.14 0 011 .95 3.39 3.39 0 01.33 1.58v2.25a3.35 3.35 0 01-.33 1.57 2.17 2.17 0 01-1 .95 4 4 0 01-1.68.32h-1.75zM425.76 207.27h.95l2.93 7.93h-.88l-2.52-7.11-2.53 7.11h-.87zm-1.57 5.27h4.17v.73h-4.17zM435.82 211.15v1.16a3.8 3.8 0 01-.31 1.65 2.06 2.06 0 01-.92 1 3.26 3.26 0 01-1.55.33 3.47 3.47 0 01-1.56-.31 2 2 0 01-.93-.93 3.4 3.4 0 01-.31-1.55v-2.34a4 4 0 01.3-1.65 2.13 2.13 0 01.93-1 3.35 3.35 0 011.54-.32 3.07 3.07 0 011.33.26 2.21 2.21 0 01.91.78 3.62 3.62 0 01.5 1.31h-.85a2.66 2.66 0 00-.39-.9 1.63 1.63 0 00-.63-.54 2 2 0 00-.87-.18 2.34 2.34 0 00-1.11.24 1.62 1.62 0 00-.66.75 3 3 0 00-.22 1.24v2.34a2.55 2.55 0 00.22 1.14 1.47 1.47 0 00.68.69 2.48 2.48 0 001.12.23 2.2 2.2 0 001.09-.24 1.38 1.38 0 00.64-.72 3.06 3.06 0 00.22-1.26v-.45h-1.92v-.73zM442.37 215.2h-.79v-7.27l-1.45.91V208l1.12-.75h1.12zM445.05 215a1.94 1.94 0 01-.82-.68 2.33 2.33 0 01-.39-1.08h.79a1.65 1.65 0 00.27.68 1.31 1.31 0 00.55.43 1.86 1.86 0 00.77.15 1.53 1.53 0 001.1-.38 1.42 1.42 0 00.39-1.07v-.24a1.38 1.38 0 00-.38-1 1.43 1.43 0 00-1.06-.37h-.56v-.73h.56a1.38 1.38 0 001-.32 1.23 1.23 0 00.34-.91v-.24a1.28 1.28 0 00-.36-1 1.39 1.39 0 00-1-.34 1.59 1.59 0 00-.66.14 1.39 1.39 0 00-.5.41 1.76 1.76 0 00-.29.65h-.8a2.6 2.6 0 01.41-1 2 2 0 01.77-.66 2.29 2.29 0 011.06-.23 2.2 2.2 0 011.59.54 2 2 0 01.56 1.52v.24a1.83 1.83 0 01-.26 1 1.6 1.6 0 01-.75.6 1.36 1.36 0 01.84.6 2.17 2.17 0 01.3 1.19v.24a2.46 2.46 0 01-.27 1.19 1.72 1.72 0 01-.77.74 2.72 2.72 0 01-1.23.26 2.66 2.66 0 01-1.2-.33zM453.79 212v.73h-3.66V212zM457.18 215.2h-.78v-7.27l-1.46.91V208l1.13-.75h1.11zM463.07 207.93l-2 7.27h-.86l2.09-7.2h-2.71v1.47h-.79v-2.2h4.31z" transform="translate(1.64)"/><path d="M683 282.77h60.29a.18.18 0 01.18.18v10.11a5.4 5.4 0 01-5.4 5.4H677.5a.18.18 0 01-.18-.18v-9.8a5.71 5.71 0 015.68-5.71z" stroke-width="1.4" stroke="#ed7320" stroke-miterlimit="10" fill="#fff"/><path class="cls-18" d="M678.29 288.52h.76l1 3.19 1-3.19h.76l-1.45 4.39h-.61zM682.29 288.52h.71v.72h-.72zm0 1.26h.71v3.13h-.72zM683.87 289.78h.72v3.13h-.72zm1.86 1.23a.59.59 0 00-.15-.43.56.56 0 00-.43-.16.53.53 0 00-.41.15.52.52 0 00-.15.4l-.06-.65a1.06 1.06 0 01.36-.44.85.85 0 01.51-.15 1 1 0 01.78.33 1.49 1.49 0 01.27.95v1.9h-.72zM686.91 293.5h.27a.2.2 0 00.15-.06.24.24 0 000-.18v-3.48h.73v3.58a.88.88 0 01-.2.61.74.74 0 01-.57.22h-.43zm.47-5h.73v.72h-.73zM689.55 292.8a1.11 1.11 0 01-.48-.48 1.65 1.65 0 01-.17-.77v-.35a1.78 1.78 0 01.16-.8 1.17 1.17 0 01.46-.5 1.54 1.54 0 01.73-.17 1.19 1.19 0 01.69.2 1.3 1.3 0 01.44.58 2.53 2.53 0 01.15.92v.21h-2.14v-.53h1.47a1 1 0 00-.18-.52.53.53 0 00-.42-.18.61.61 0 00-.5.21.84.84 0 00-.18.58v.4a.75.75 0 00.19.55.78.78 0 00.55.19 1.09 1.09 0 00.35-.07 1.08 1.08 0 00.31-.19l.48.44a1.73 1.73 0 01-.54.35 1.73 1.73 0 01-1.36 0zM692.93 292.91a2.36 2.36 0 01-.47-.16 1.6 1.6 0 01-.4-.25l.43-.54a1.89 1.89 0 00.49.25 1.46 1.46 0 00.49.09 1.09 1.09 0 00.5-.09.28.28 0 00.17-.26.24.24 0 00-.08-.19.4.4 0 00-.22-.09l-.36-.05h-.21a2.82 2.82 0 01-.54-.11.68.68 0 01-.36-.25.88.88 0 01-.14-.53 1 1 0 01.14-.54 1 1 0 01.42-.34 2 2 0 01.69-.11 1.83 1.83 0 01.47 0 2.23 2.23 0 01.44.13 3.11 3.11 0 01.4.22l-.44.53a1.58 1.58 0 00-.44-.2 1.39 1.39 0 00-.44-.07 1 1 0 00-.43.08.27.27 0 00-.15.24.19.19 0 00.08.16.44.44 0 00.21.07l.35.05h.14a2.66 2.66 0 01.58.1.77.77 0 01.39.26.89.89 0 01.16.58 1 1 0 01-.15.56.88.88 0 01-.45.34 2 2 0 01-.73.12 3.1 3.1 0 01-.54 0zM697.25 289.78h.75l-1.18 3.13h-.53l-1.18-3.13h.74l.7 2.1zM698.51 288.52h.72v.72h-.72zm0 1.26h.72v3.13h-.72zM700.09 289.78h.72v3.13h-.72zM702 291a.59.59 0 00-.15-.43.56.56 0 00-.43-.16.53.53 0 00-.41.15.52.52 0 00-.15.4l-.06-.65a1.06 1.06 0 01.36-.44.84.84 0 01.5-.15 1 1 0 01.78.33 1.44 1.44 0 01.28.95v1.9H702zM704 292.81a1 1 0 01-.37-.45 1.88 1.88 0 01-.12-.71v-.6a1.94 1.94 0 01.12-.72.91.91 0 01.36-.45 1.06 1.06 0 01.57-.16.86.86 0 01.49.15 1 1 0 01.35.42l-.06.67a.59.59 0 00-.07-.31.37.37 0 00-.18-.19.62.62 0 00-.71.1.74.74 0 00-.15.49v.6a.69.69 0 00.15.48.62.62 0 00.71.1.41.41 0 00.18-.19.62.62 0 00.07-.31v.69a.82.82 0 01-.8.55 1.07 1.07 0 01-.54-.16zm0 1.25a1.1 1.1 0 01-.45-.37l.49-.45a.71.71 0 00.27.22.8.8 0 00.33.08.69.69 0 00.49-.17.61.61 0 00.18-.47v-3.12h.69v3a1.53 1.53 0 01-.16.74 1.12 1.12 0 01-.47.47 1.6 1.6 0 01-.75.16 1.51 1.51 0 01-.62-.09zM707.45 292.8a1.14 1.14 0 01-.49-.48 1.65 1.65 0 01-.16-.77v-.35a1.78 1.78 0 01.16-.8 1.12 1.12 0 01.46-.5 1.49 1.49 0 01.73-.17 1.19 1.19 0 01.69.2 1.29 1.29 0 01.43.58 2.53 2.53 0 01.15.92v.21h-2.13v-.53h1.46a.9.9 0 00-.19-.52.51.51 0 00-.41-.18.64.64 0 00-.51.21.89.89 0 00-.17.58v.4a.75.75 0 00.19.55.77.77 0 00.54.19 1.15 1.15 0 00.36-.07 1.23 1.23 0 00.31-.19l.47.44a1.73 1.73 0 01-.54.35 1.53 1.53 0 01-.6.12 1.57 1.57 0 01-.75-.19zM710.21 289.78h.72v3.13h-.72zm1.86 1.23a.59.59 0 00-.15-.43.56.56 0 00-.43-.16.53.53 0 00-.41.15.52.52 0 00-.15.4l-.06-.65a1.06 1.06 0 01.36-.44.85.85 0 01.51-.15 1 1 0 01.78.33 1.49 1.49 0 01.27.95v1.9h-.72zM718.72 288.52h.73v4.39h-.73zm.39 1.88h2.5v.69h-2.5zm2.07-1.88h.72v4.39h-.72zM723 292.72a.92.92 0 01-.27-.73.88.88 0 01.27-.7 1.25 1.25 0 01.82-.23h.84v.56h-.88a.47.47 0 00-.32.09.32.32 0 00-.11.28.33.33 0 00.14.29.76.76 0 00.42.1 1.29 1.29 0 00.51-.08.25.25 0 00.17-.23l.06.44a.49.49 0 01-.18.25.75.75 0 01-.31.15 1.6 1.6 0 01-.39 0 1.17 1.17 0 01-.77-.19zm1.63-1.8a.49.49 0 00-.16-.4.6.6 0 00-.44-.15 1 1 0 00-.35.06 1.07 1.07 0 00-.32.16l-.48-.41a1.21 1.21 0 01.48-.33 1.81 1.81 0 01.67-.12 1.55 1.55 0 01.68.14 1 1 0 01.44.4 1.22 1.22 0 01.15.63v2h-.67zM726.16 289.78h.73v3.13h-.73zM728 291a.6.6 0 00-.16-.43.54.54 0 00-.43-.16.5.5 0 00-.55.55l-.07-.65a1.24 1.24 0 01.36-.44.9.9 0 01.51-.15 1 1 0 01.78.33 1.49 1.49 0 01.28.95v1.9H728zM730 292.81a.93.93 0 01-.37-.45 1.87 1.87 0 01-.13-.71v-.6a1.93 1.93 0 01.13-.72.91.91 0 01.36-.45 1.06 1.06 0 01.57-.16.86.86 0 01.49.15 1.13 1.13 0 01.35.42l-.07.67a.71.71 0 00-.06-.31.37.37 0 00-.18-.19.56.56 0 00-.3-.07.51.51 0 00-.41.17.74.74 0 00-.15.49v.6a.69.69 0 00.15.48.51.51 0 00.41.17.56.56 0 00.3-.07.41.41 0 00.18-.19.75.75 0 00.06-.31v.69a1 1 0 01-.3.4.84.84 0 01-.5.15 1.07 1.07 0 01-.53-.16zm1.33-4.29h.73v4.39h-.73zM733.52 292.8a1.11 1.11 0 01-.48-.48 1.65 1.65 0 01-.17-.77v-.35a1.93 1.93 0 01.16-.8 1.14 1.14 0 01.47-.5 1.49 1.49 0 01.73-.17 1.19 1.19 0 01.68.2 1.24 1.24 0 01.44.58 2.53 2.53 0 01.15.92v.21h-2.13v-.53h1.46a1 1 0 00-.19-.52.51.51 0 00-.41-.18.64.64 0 00-.51.21.84.84 0 00-.18.58v.4a.76.76 0 00.2.55.77.77 0 00.54.19 1 1 0 00.35-.07 1.29 1.29 0 00.32-.19l.47.44a1.73 1.73 0 01-.54.35 1.73 1.73 0 01-1.36 0zM737 292a.24.24 0 00.06.18.21.21 0 00.16.06h.22v.69h-.4a.73.73 0 01-.56-.21.86.86 0 01-.2-.62v-3.57h.72z" transform="translate(1.64)"/><path d="M720.79 282.77c-.18.63-.55 1.78-1.29 3.67-1.24 3.19-3 5.09-2.47 7.14s2 3 4.82 3.84a45.51 45.51 0 004.73 1.05l-.74-.13" stroke="#ed7320" stroke-width=".93" stroke-miterlimit="10" fill="none"/>
+ </svg>
+</div>
+<div class="container">
+ <div class="row my-5">
+ @if (Model.HighlightedProducts.Any(c => c.IsAvailable && c.IsVisible)) {
+ <h2>Favorittar</h2>
+ <div class="favorites">
+ @foreach (var product in Model.HighlightedProducts.Where(c => c.IsVisible && c.IsAvailable).OrderByDescending(c => c.Updated)) {
+ <a href="@product.WebPath()" class="favorite-card">
+ <img src="@product.GetPrimaryImage().WebPath" class="lazyload blur-up" alt="...">
+ <h3 class="mt-2">@product.Name</h3>
+ </a>
+ }
+ </div>
+ }
+ </div>
+ <div class="row contact-section" id="kontakt">
+ @Html.Raw(Model.ContactHtml)
+ </div>
+</div> \ No newline at end of file
diff --git a/src/Pages/Index.cshtml.cs b/src/Pages/Index.cshtml.cs
new file mode 100644
index 0000000..3cefa0d
--- /dev/null
+++ b/src/Pages/Index.cshtml.cs
@@ -0,0 +1,34 @@
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.EntityFrameworkCore;
+using VSH.Data;
+using VSH.Data.Database;
+using VSH.Data.Enums;
+
+namespace VSH.Pages;
+
+public class IndexModel : PageModel
+{
+ private readonly MainDbContext _context;
+
+ public string ContactHtml { get; set; }
+ public List<Product> HighlightedProducts { get; set; } = new();
+
+ public IndexModel(MainDbContext context) {
+ _context = context;
+ }
+
+ public ActionResult OnGet() {
+ ContactHtml = _context.Documents.OrderBy(c => c.Created)
+ .LastOrDefault(c => c.Type == DocumentType.CONTACT_PAGE)
+ ?.Content;
+ HighlightedProducts = _context.Products
+ .Where(c => c.ShowOnFrontpage
+ && c.VisibilityState == ProductVisibility.DEFAULT)
+ .Include(c => c.Category)
+ .ToList();
+ return Page();
+ }
+} \ No newline at end of file
diff --git a/src/Pages/Kontoret/Bestillinger.cshtml b/src/Pages/Kontoret/Bestillinger.cshtml
new file mode 100644
index 0000000..961e12a
--- /dev/null
+++ b/src/Pages/Kontoret/Bestillinger.cshtml
@@ -0,0 +1,67 @@
+@page
+@model VSH.Pages.Kontoret.Bestillinger
+@{
+ ViewData["Title"] = "Bestillinger";
+}
+<div class="d-flex justify-content-center my-5" id="orders-loader">
+ <div class="spinner-border" role="status">
+ <span class="visually-hidden">Laster...</span>
+ </div>
+</div>
+<div id="orders-wrapper" class="d-none py-3"></div>
+
+<div id="order-info-modal" tabindex="-1" class="modal">
+ <div class="modal-dialog modal-dialog-scrollable modal-lg">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title"></h5>
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+ </div>
+ <div class="modal-body">
+ <div id="loader">
+ <div class="spinner-border text-primary" role="status">
+ <span class="visually-hidden">Loading...</span>
+ </div>
+ </div>
+ <div id="loaded">
+ <span class="text-bold">Betalingsmetode:</span> <span id="order-payment-type"></span> <br>
+ <div class="ps-5 d-none" id="vipps-section">
+ <span class="text-bold">Vipps - status:</span> <span id="vipps-status"></span> <br>
+ <span class="text-bold">Vipps - lenke:</span> <span id="vipps-link"></span> <br>
+ <button id="vipps-order-capture" class="btn btn-link d-none" title="Trykk her for å signalisere om levert bestilling">
+ <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
+ Bestillingen er levert
+ </button>
+ <button id="vipps-order-refund" class="btn btn-link d-none" title="Trykk her for å refundere bestillingen hos vipps">
+ <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
+ Bestillingen er refundert
+ </button>
+ <button id="vipps-order-cancel" class="btn btn-link d-none" title="Trykk her for å kansellere bestillingen hos vipps">
+ <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
+ Bestillingen er kansellert
+ </button>
+ </div>
+ <span class="text-bold">Status:</span> <span id="order-status"></span> <br>
+ <span class="text-bold">Navn:</span> <span id="contact-info-name"></span> <br>
+ <span class="text-bold">E-postadresse:</span> <span id="contact-info-emailAddress"></span> <br>
+ <span class="text-bold">Telefon:</span> <span id="contact-info-phoneNumber"></span> <br>
+ <span class="text-bold">Referanse:</span> <span id="order-reference"></span> <br>
+ <span class="text-bold">Bestillingsdato:</span> <span id="order-date"></span> <br>
+ <span class="text-bold">Totalt:</span> <span id="order-total"></span> <br>
+ <span class="text-bold">Kommentar:</span> <span id="order-comment"></span>
+ <table class="table">
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col">Navn</th>
+ <th scope="col">Antall</th>
+ <th scope="col">Pris</th>
+ </tr>
+ </thead>
+ <tbody></tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/src/Pages/Kontoret/Bestillinger.cshtml.cs b/src/Pages/Kontoret/Bestillinger.cshtml.cs
new file mode 100644
index 0000000..8aff3c4
--- /dev/null
+++ b/src/Pages/Kontoret/Bestillinger.cshtml.cs
@@ -0,0 +1,8 @@
+using Microsoft.AspNetCore.Mvc.RazorPages;
+
+namespace VSH.Pages.Kontoret;
+
+public class Bestillinger : PageModel
+{
+ public void OnGet() { }
+} \ No newline at end of file
diff --git a/src/Pages/Kontoret/Dokumenter.cshtml b/src/Pages/Kontoret/Dokumenter.cshtml
new file mode 100644
index 0000000..55e0ba6
--- /dev/null
+++ b/src/Pages/Kontoret/Dokumenter.cshtml
@@ -0,0 +1,21 @@
+@page
+@using VSH.Data.Enums
+@using VSH.Utilities
+@using IOL.Helpers
+@model VSH.Pages.Kontoret.Dokumenter
+@{
+ ViewData["Title"] = "Dokumenter";
+}
+
+<div class="d-flex mb-3">
+ <select name="document-selector" id="document-selector" class="form-select">
+ @foreach (var option in EnumHelpers.GetValues<DocumentType>()) {
+ <option value="@(option)">@EnumName.ForDocumentType(option)</option>
+ }
+ </select>
+ <button class="btn btn-outline-primary ms-3 fs-3" id="publish-button" title="Publiser">
+ <i class="bi bi-cloud-upload"></i>
+ </button>
+</div>
+
+<div id="editor"></div> \ No newline at end of file
diff --git a/src/Pages/Kontoret/Dokumenter.cshtml.cs b/src/Pages/Kontoret/Dokumenter.cshtml.cs
new file mode 100644
index 0000000..ca72b4e
--- /dev/null
+++ b/src/Pages/Kontoret/Dokumenter.cshtml.cs
@@ -0,0 +1,8 @@
+using Microsoft.AspNetCore.Mvc.RazorPages;
+
+namespace VSH.Pages.Kontoret;
+
+public class Dokumenter : PageModel
+{
+ public void OnGet() { }
+} \ No newline at end of file
diff --git a/src/Pages/Kontoret/Produkter.cshtml b/src/Pages/Kontoret/Produkter.cshtml
new file mode 100644
index 0000000..825005d
--- /dev/null
+++ b/src/Pages/Kontoret/Produkter.cshtml
@@ -0,0 +1,18 @@
+@page
+@model VSH.Pages.Kontoret.Produkter2
+@{
+ ViewData["Title"] = "Produkter";
+}
+
+<button class="btn btn-primary" id="open-product-modal">Legg til produkt</button>
+<button class="btn btn-primary" id="open-categories-modal">Åpne kategorier</button>
+
+<div class="d-flex justify-content-center my-5" id="products-loader">
+ <div class="spinner-border" role="status">
+ <span class="visually-hidden">Laster...</span>
+ </div>
+</div>
+<div id="products" class="d-none py-3"></div>
+
+<partial name="Partials/_AdminProductModal"/>
+<partial name="Partials/_AdminCategoriesModal"/> \ No newline at end of file
diff --git a/src/Pages/Kontoret/Produkter.cshtml.cs b/src/Pages/Kontoret/Produkter.cshtml.cs
new file mode 100644
index 0000000..0d16e08
--- /dev/null
+++ b/src/Pages/Kontoret/Produkter.cshtml.cs
@@ -0,0 +1,8 @@
+using Microsoft.AspNetCore.Mvc.RazorPages;
+
+namespace VSH.Pages.Kontoret;
+
+public class Produkter2 : PageModel
+{
+ public void OnGet() { }
+} \ No newline at end of file
diff --git a/src/Pages/Kontoret/_ViewImports.cshtml b/src/Pages/Kontoret/_ViewImports.cshtml
new file mode 100644
index 0000000..01f3f6a
--- /dev/null
+++ b/src/Pages/Kontoret/_ViewImports.cshtml
@@ -0,0 +1,3 @@
+@using VSH
+@namespace VSH.Pages.Kontoret
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
diff --git a/src/Pages/Kontoret/_ViewStart.cshtml b/src/Pages/Kontoret/_ViewStart.cshtml
new file mode 100644
index 0000000..0297c66
--- /dev/null
+++ b/src/Pages/Kontoret/_ViewStart.cshtml
@@ -0,0 +1,3 @@
+@{
+ Layout = "_AdminLayout";
+} \ No newline at end of file
diff --git a/src/Pages/Leverandorar.cshtml b/src/Pages/Leverandorar.cshtml
new file mode 100644
index 0000000..eb712a5
--- /dev/null
+++ b/src/Pages/Leverandorar.cshtml
@@ -0,0 +1,9 @@
+@page "/leverandørar"
+@model VSH.Pages.Leverandorar
+@{
+ ViewData["Title"] = "Leverandørar";
+}
+
+<div class="container py-3 py-md-5 dynamic-content">
+ @Html.Raw(Model.DealersPageHtml)
+</div> \ No newline at end of file
diff --git a/src/Pages/Leverandorar.cshtml.cs b/src/Pages/Leverandorar.cshtml.cs
new file mode 100644
index 0000000..e8f467b
--- /dev/null
+++ b/src/Pages/Leverandorar.cshtml.cs
@@ -0,0 +1,23 @@
+using System.Linq;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.EntityFrameworkCore;
+using VSH.Data;
+using VSH.Data.Enums;
+
+namespace VSH.Pages;
+
+public class Leverandorar : PageModel
+{
+ private readonly MainDbContext _context;
+
+ public Leverandorar(MainDbContext context) {
+ context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
+ _context = context;
+ }
+
+ public string DealersPageHtml { get; set; }
+
+ public void OnGet() {
+ DealersPageHtml = _context.Documents.FirstOrDefault(c => c.Type == DocumentType.DEALERS_PAGE)?.Content;
+ }
+} \ No newline at end of file
diff --git a/src/Pages/LoggInn.cshtml b/src/Pages/LoggInn.cshtml
new file mode 100644
index 0000000..6349466
--- /dev/null
+++ b/src/Pages/LoggInn.cshtml
@@ -0,0 +1,34 @@
+@page
+@using Microsoft.AspNetCore.Antiforgery
+@model VSH.Pages.LoggInn
+@inject IAntiforgery Antiforgery
+@{
+ ViewData["Title"] = "Logg inn";
+ var token = Antiforgery.GetAndStoreTokens(HttpContext).RequestToken;
+}
+
+<div class="container mw-450px py-3 py-md-5">
+ <div class="alert alert-danger d-none" id="error" role="alert">
+ <h4 class="alert-header" id="error-title"></h4>
+ <p class="mb-0" id="error-message"></p>
+ </div>
+ <form id="login-form" onsubmit="return false">
+ <div class="mb-3">
+ <label for="input-email" class="form-label">E-postadresse</label>
+ <input type="email" class="form-control" name="input-email" id="input-email" placeholder="navn@domene.no" autofocus required>
+ </div>
+ <div class="mb-3">
+ <label for="input-password" class="form-label">Passord</label>
+ <input type="password" class="form-control" name="input-password" id="input-password" required>
+ </div>
+ <div class="mb-3 form-check">
+ <input type="checkbox" class="form-check-input" id="persist-session">
+ <label class="form-check-label" for="persist-session">Husk meg</label>
+ </div>
+ <input type="hidden" name="xsrf" value="@token">
+ <button type="submit" id="submit" class="btn btn-primary float-right">
+ <span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
+ Logg inn
+ </button>
+ </form>
+</div>
diff --git a/src/Pages/LoggInn.cshtml.cs b/src/Pages/LoggInn.cshtml.cs
new file mode 100644
index 0000000..d4ee7d7
--- /dev/null
+++ b/src/Pages/LoggInn.cshtml.cs
@@ -0,0 +1,19 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+
+namespace VSH.Pages;
+
+public class LoggInn : PageModel
+{
+ public ActionResult OnGet() {
+ if (User.Identity?.IsAuthenticated ?? false) {
+ if (Request.Query.ContainsKey("ReturnUrl")) {
+ return Redirect(Request.Query["ReturnUrl"]);
+ }
+
+ return Redirect("/kontoret");
+ }
+
+ return Page();
+ }
+} \ No newline at end of file
diff --git a/src/Pages/OmOss.cshtml b/src/Pages/OmOss.cshtml
new file mode 100644
index 0000000..0ba277c
--- /dev/null
+++ b/src/Pages/OmOss.cshtml
@@ -0,0 +1,9 @@
+@page "/om-oss"
+@model VSH.Pages.OmOss
+@{
+ ViewData["Title"] = "Om oss";
+}
+
+<div class="container py-3 py-md-5 dynamic-content">
+ @Html.Raw(Model.AboutUsPageHtml)
+</div> \ No newline at end of file
diff --git a/src/Pages/OmOss.cshtml.cs b/src/Pages/OmOss.cshtml.cs
new file mode 100644
index 0000000..217f829
--- /dev/null
+++ b/src/Pages/OmOss.cshtml.cs
@@ -0,0 +1,23 @@
+using System.Linq;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.EntityFrameworkCore;
+using VSH.Data;
+using VSH.Data.Enums;
+
+namespace VSH.Pages;
+
+public class OmOss : PageModel
+{
+ private readonly MainDbContext _context;
+
+ public OmOss(MainDbContext context) {
+ context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
+ _context = context;
+ }
+
+ public string AboutUsPageHtml { get; set; }
+
+ public void OnGet() {
+ AboutUsPageHtml = _context.Documents.FirstOrDefault(c => c.Type == DocumentType.ABOUT_PAGE)?.Content;
+ }
+} \ No newline at end of file
diff --git a/src/Pages/Partials/_AdminCategoriesModal.cshtml b/src/Pages/Partials/_AdminCategoriesModal.cshtml
new file mode 100644
index 0000000..ee52f2a
--- /dev/null
+++ b/src/Pages/Partials/_AdminCategoriesModal.cshtml
@@ -0,0 +1,25 @@
+<div class="modal" tabindex="-1" id="categories-modal">
+ <div class="modal-dialog modal-dialog-scrollable modal-lg">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title">Kategorier</h5>
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+ </div>
+ <div class="modal-body">
+ <div class="card">
+ <div class="card-header p-3">
+ <form onsubmit="return false;" id="new-category-form">
+ <input type="text" class="form-control" id="new-category-name" name="new-category-name" placeholder="Legg til en ny kategori" autocomplete="off" required>
+ </form>
+ </div>
+ <div class="d-flex justify-content-center p-3" id="loading-wrapper">
+ <div class="spinner-border" role="status">
+ <span class="visually-hidden">Laster...</span>
+ </div>
+ </div>
+ <div class="list-group list-group-flush d-none" id="list-wrapper"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/src/Pages/Partials/_AdminProductModal.cshtml b/src/Pages/Partials/_AdminProductModal.cshtml
new file mode 100644
index 0000000..06cbc81
--- /dev/null
+++ b/src/Pages/Partials/_AdminProductModal.cshtml
@@ -0,0 +1,72 @@
+<div class="modal" tabindex="-1" id="product-modal">
+ <div class="modal-dialog modal-dialog-scrollable modal-lg">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title" id="product-modal-title">Nytt produkt</h5>
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+ </div>
+ <div class="modal-body">
+ <form class="margin-bottom-sm" id="product-form">
+ <div class="loader">
+ <div class="spinner-border" role="status">
+ <span class="visually-hidden">Laster...</span>
+ </div>
+ </div>
+ <fieldset class="mb-3">
+ <label class="form-label mb-2" for="input-name">Navn</label>
+ <input class="form-control" type="text" name="input-name" id="input-name" required/>
+ </fieldset>
+ <fieldset class="mb-3 row">
+ <div class="col">
+ <label class="form-label mb-2" for="input-price">Pris</label>
+ <div class="input-group">
+ <input class="form-control" type="text" name="input-price" id="input-price" required/>
+ <select class="form-select" style="max-width: 85px;" id="input-price-suffix">
+ <option selected value="0">,-</option>
+ <option value="1">,- kg</option>
+ </select>
+ </div>
+ </div>
+ <div class="col">
+ <label class="form-label mb-2" for="input-count">Besetning (-1 for uendelig)</label>
+ <div class="input-group">
+ <input class="form-control" type="number" min="-1" name="input-count" id="input-count" placeholder="Antall produkter/kilo for salg"/>
+ </div>
+ </div>
+ </fieldset>
+ <fieldset class="mb-3">
+ <label class="form-label mb-2" for="input-description">Beskrivelse</label>
+ <textarea class="form-control" name="input-description" id="input-description"></textarea>
+ </fieldset>
+ <fieldset class="mb-3">
+ <label for="" class="form-label mb-2">Bilder</label>
+ <div class="row pb-2" id="input-images-row">
+ </div>
+ </fieldset>
+ <fieldset class="form-check form-switch mb-3">
+ <input class="form-check-input" type="checkbox" id="show-on-frontpage" name="show-on-frontpage">
+ <label class="form-check-label" for="show-on-frontpage">Vis på forsiden</label>
+ </fieldset>
+ <fieldset class="mb-3">
+ <label for="" class="form-label mb-2">Kategori</label>
+ <div id="product-category-picker-wrapper">
+ <div id="picker" class="d-none"></div>
+ <div class="d-flex justify-content-center" id="loader">
+ <div class="spinner-border" role="status">
+ <span class="visually-hidden">Laster...</span>
+ </div>
+ </div>
+ </div>
+ </fieldset>
+ </form>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-lg btn-secondary" data-bs-dismiss="modal">Avbryt</button>
+ <button type="button" class="btn btn-lg btn-primary" id="submit-product-form">
+ <span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
+ <span class="text">Lagre</span>
+ </button>
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/src/Pages/Partials/_CultureSelector.cshtml b/src/Pages/Partials/_CultureSelector.cshtml
new file mode 100644
index 0000000..07965f9
--- /dev/null
+++ b/src/Pages/Partials/_CultureSelector.cshtml
@@ -0,0 +1,35 @@
+@using Microsoft.AspNetCore.Builder
+@using Microsoft.AspNetCore.Localization
+@using Microsoft.Extensions.Localization
+@using Microsoft.Extensions.Options
+@using IOL.Helpers
+
+@inject IStringLocalizer<SharedPageResources> Localizer
+@inject IOptions<RequestLocalizationOptions> LocOptions
+
+@{
+ var requestCulture = Context.Features.Get<IRequestCultureFeature>();
+ var cultureItems = LocOptions.Value.SupportedUICultures;
+}
+
+<div>
+ <form asp-controller="Root"
+ asp-action="SetCulture"
+ asp-route-returnUrl="@Context.Request.Path"
+ method="post"
+ class="row row-cols-lg-auto g-3 align-items-center"
+ role="form">
+ <div class="col">
+ <select class="form-control" name="culture">
+ @foreach (var item in cultureItems) {
+ if (item.Name == requestCulture?.RequestCulture.UICulture.Name) {
+ <option value="@item.Name" selected>@item.NativeName.Capitalize()</option>
+ } else {
+ <option value="@item.Name">@item.NativeName.Capitalize()</option>
+ }
+ }
+ </select>
+ </div>
+ <button type="submit" class="btn btn-default btn-xs">@Localizer["Lagre"]</button>
+ </form>
+</div> \ No newline at end of file
diff --git a/src/Pages/Personvern.cshtml b/src/Pages/Personvern.cshtml
new file mode 100644
index 0000000..83d5043
--- /dev/null
+++ b/src/Pages/Personvern.cshtml
@@ -0,0 +1,8 @@
+@page
+@model PrivacyModel
+@{
+ ViewData["Title"] = "Personvern";
+}
+<div class="container py-3 py-md-5 dynamic-content">
+ @Html.Raw(Model.PrivacyPolicyHtml)
+</div> \ No newline at end of file
diff --git a/src/Pages/Personvern.cshtml.cs b/src/Pages/Personvern.cshtml.cs
new file mode 100644
index 0000000..1a661c5
--- /dev/null
+++ b/src/Pages/Personvern.cshtml.cs
@@ -0,0 +1,25 @@
+using System.Linq;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.EntityFrameworkCore;
+using VSH.Data;
+using VSH.Data.Enums;
+
+namespace VSH.Pages;
+
+public class PrivacyModel : PageModel
+{
+ private readonly MainDbContext _context;
+
+ public PrivacyModel(MainDbContext context) {
+ context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
+ _context = context;
+ }
+
+ public string PrivacyPolicyHtml { get; set; }
+
+ public void OnGet() {
+ PrivacyPolicyHtml = _context.Documents.OrderBy(c => c.Created)
+ .LastOrDefault(c => c.Type == DocumentType.PRIVACY_POLICY)
+ ?.Content;
+ }
+} \ No newline at end of file
diff --git a/src/Pages/Produktar.cshtml b/src/Pages/Produktar.cshtml
new file mode 100644
index 0000000..f43e4ab
--- /dev/null
+++ b/src/Pages/Produktar.cshtml
@@ -0,0 +1,163 @@
+@page "{categorySlug?}/{productSlug?}"
+@using VSH.Data.Static
+@using IOL.Helpers
+@model VSH.Pages.Produktar
+@{
+ var title = "Produktar";
+ if (Model.IsProduct) {
+ title = Model.CurrentProduct.Name;
+ } else if (Model.IsCategory) {
+ title = Model.Categories.FirstOrDefault()?.Name;
+ }
+
+ ViewData["Title"] = title;
+}
+
+<div class="container py-3 py-md-5">
+ @if (Model.IsCategory || Model.IsProduct) {
+ <nav aria-label="breadcrumb" class="pt-3">
+ <ol class="breadcrumb">
+ @if (Model.Categories?.Count == 1) {
+ <li class="breadcrumb-item">
+ <a href="/produktar">Produktar</a>
+ </li>
+ <li class="breadcrumb-item active" aria-current="page">
+ @Model.Categories.SingleOrDefault()?.Name
+ </li>
+ }
+ @if (Model.IsProduct) {
+ <li class="breadcrumb-item">
+ <a href="/produktar">Produktar</a>
+ </li>
+ <li class="breadcrumb-item">
+ <a href="/produktar/@Model.CategorySlug">@Model.CurrentProduct.Category.Name</a>
+ </li>
+ <li class="breadcrumb-item active" aria-current="page">
+ @Model.CurrentProduct.Name
+ </li>
+ }
+ </ol>
+ </nav>
+ }
+
+ @if (Model.IsProduct) {
+ <div class="row" id="single-product-wrapper" data-id="@Model.CurrentProduct.Id">
+ <div class="col-12 col-md-6">
+ @if (Model.CurrentProduct.Images.Any()) {
+ if (Model.CurrentProduct.Images.Count > 1) {
+ <div id="product-carousel" class="carousel">
+ <div class="carousel-inner">
+ @{ var index = 0; }
+ @foreach (var secondaryImage in Model.CurrentProduct.Images.OrderBy(c => c.Order)) {
+ <div class="carousel-item @(index == 0 ? "active" : "")">
+ <img src="@secondaryImage.GetPath().WebPath" class="d-block w-100 @(index == 0 ? "lazyload blur-up" : "")" alt="">
+ </div>
+ index++;
+ }
+ </div>
+ </div>
+ <div class="d-flex justify-content-start flex-wrap mt-2" id="carousel-navigator">
+ @{ var secIndex = 0; }
+ @foreach (var secondaryImage in Model.CurrentProduct.Images.OrderBy(c => c.Order)) {
+ <div class="px-1 thumb-button cursor-pointer" data-thumb-index="@secIndex">
+ <img src="@secondaryImage.GetPath().WebPath" class="img-thumbnail lazyload blur-up border-0" alt="">
+ </div>
+ secIndex++;
+ }
+ </div>
+ } else {
+ var fileName = Model.CurrentProduct.GetPrimaryImage();
+ <img src="@(fileName.WebPath.ExtractFileName() + "-150" + fileName.WebPath.ExtractExtension())"
+ data-src="@fileName.WebPath"
+ class="card-img-top lazyload blur-up"
+ alt="Bilde av produktet">
+ }
+ } else {
+ <img src="/assets/profile/innrammet.svg"
+ data-src="/assets/profile/innrammet.svg"
+ class="card-img-top lazyload blur-up placeholder p-5"
+ alt="Bilde av produktet">
+ }
+ </div>
+ <div class="col-12 pt-3 col-md-6">
+ <div class="row">
+ <h2 class="title">@Model.CurrentProduct.Name</h2>
+ <p class="description">@Model.CurrentProduct.Description</p>
+ </div>
+ <div class="row">
+ <div class="col d-flex justify-content-end align-items-center buttons">
+ @if (Model.CurrentProduct.IsAvailable) {
+ <div class="add-to-cart-button">
+ <div class="counter-wrapper"></div>
+ <button class="btn btn-outline-primary shadow-none disabled bag-button" data-product-max-count="@Model.CurrentProduct.Count">
+ <div class="spinner-border text-primary" role="status">
+ <span class="visually-hidden">Loading...</span>
+ </div>
+ </button>
+ <span class="product-price text-bold" data-price="@Model.CurrentProduct.Price">@Model.CurrentProduct.Price@(Model.CurrentProduct.ReadablePriceSuffix)</span>
+ </div>
+ } else {
+ <button class="btn btn-lg btn-outline-primary shadow-none disabled">
+ Utselt
+ </button>
+ }
+ </div>
+ </div>
+ </div>
+ </div>
+ } else if ((Model.IsCategory || Model.IsCategories) && Model.Categories?.Count >= 1) {
+ foreach (var category in Model.Categories.Where(category => category.Products.Count >= 1)) {
+ <div class="row mb-3">
+ <h2 class="h2">@category.Name</h2>
+ @foreach (var product in category.Products.Where(c => c.IsVisible)) {
+ <div class="col-sm-12 col-md-6 col-xl-3 p-1 px-2 mb-3">
+ <div class="card product-card" data-id="@product.Id">
+ @if (product.Images.Any()) {
+ var fileName = product.GetPrimaryImage();
+ <a href="@product.WebPath()">
+ <img src="@(fileName.WebPath.ExtractFileName() + "-150" + fileName.WebPath.ExtractExtension())"
+ data-src="@fileName.WebPath"
+ class="card-img-top lazyload blur-up"
+ alt="">
+ </a>
+ } else {
+ <a href="@product.WebPath()">
+ <img src="@AppPaths.DefaultProductImage.WebPath"
+ data-src="@AppPaths.DefaultProductImage.WebPath"
+ class="card-img-top lazyload blur-up placeholder"
+ alt="">
+ </a>
+ }
+ <div class="card-body">
+ <a class="card-title fs-3 text-reset text-decoration-none" href="@product.WebPath()">
+ @product.Name
+ </a>
+ <div class="d-flex justify-content-end align-items-center pt-1 buttons">
+ @if (product.IsAvailable) {
+ <div class="add-to-cart-button">
+ <div class="counter-wrapper"></div>
+ <button class="btn btn-outline-primary shadow-none disabled bag-button" data-product-max-count="@product.Count">
+ <div class="spinner-border text-primary" role="status">
+ <span class="visually-hidden">Loading...</span>
+ </div>
+ </button>
+ <span class="product-price text-bold" data-price="@product.Price">@product.Price@(product.ReadablePriceSuffix)</span>
+ </div>
+ } else {
+ <button class="btn btn-link float-right shadow-none disabled">
+ Utselt
+ </button>
+ }
+ </div>
+ </div>
+ </div>
+ </div>
+ }
+ </div>
+ }
+ } else {
+ <h2>
+ Heisann, her er det tomt for augneblinken. Prøv igjen snart.
+ </h2>
+ }
+</div> \ No newline at end of file
diff --git a/src/Pages/Produktar.cshtml.cs b/src/Pages/Produktar.cshtml.cs
new file mode 100644
index 0000000..b0ba470
--- /dev/null
+++ b/src/Pages/Produktar.cshtml.cs
@@ -0,0 +1,82 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using IOL.Helpers;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Localization;
+using Microsoft.Extensions.Options;
+using VSH.Data.Miscellaneous;
+using VSH.Data.Database;
+using VSH.Data;
+using VSH.Data.Enums;
+using VSH.Data.Static;
+
+namespace VSH.Pages;
+
+public class Produktar : PageModel
+{
+ private readonly MainDbContext _context;
+ private readonly IStringLocalizer<SharedPageResources> _localizer;
+ private readonly IOptions<AppSettings.GeneralConfiguration> _options;
+
+ public string ProductSlug { get; set; }
+ public string CategorySlug { get; set; }
+ public bool IsProduct { get; set; }
+ public bool IsCategory { get; set; }
+ public bool IsCategories { get; set; }
+ public Product CurrentProduct { get; set; }
+
+ public Produktar(
+ MainDbContext context,
+ IStringLocalizer<SharedPageResources> localizer,
+ IOptions<AppSettings.GeneralConfiguration> options
+ ) {
+ _context = context;
+ _localizer = localizer;
+ _options = options;
+ }
+
+ public List<Category> Categories { get; set; }
+
+ public ActionResult OnGet(string categorySlug, string productSlug) {
+ ProductSlug = productSlug;
+ CategorySlug = categorySlug;
+
+ if (ProductSlug.HasValue()) {
+ CurrentProduct = _context.Products.Where(c => c.VisibilityState == ProductVisibility.DEFAULT)
+ .Include(c => c.Category)
+ .SingleOrDefault(p => p.Slug == ProductSlug);
+ IsProduct = CurrentProduct != default;
+ if (!IsProduct)
+ return Page();
+ var productImage = CurrentProduct != null && CurrentProduct.Images.Any()
+ ? CurrentProduct.Images.OrderBy(c => c.Order).FirstOrDefault()
+ : default;
+
+ ViewData["open_graph"] = new OpenGraphData {
+ Description = CurrentProduct?.Description,
+ Image = productImage != default
+ ? (HttpContext.Request.GetRequestHost()
+ + Path.Combine(AppPaths.ProductImages.WebPath, productImage.FileName))
+ : default,
+ Title = $"{CurrentProduct?.Name} {_localizer["frå"]} {_options.Value.StoreName}",
+ };
+ } else if (CategorySlug.HasValue()) {
+ Categories = _context
+ .Categories.Where(c => c.Slug == CategorySlug
+ && c.VisibilityState == CategoryVisibility.DEFAULT)
+ .Include(c => c.Products)
+ .ToList();
+ IsCategory = !IsProduct && Categories?.Count == 1;
+ } else {
+ Categories = _context.Categories.Where(c => c.VisibilityState == CategoryVisibility.DEFAULT)
+ .Include(c => c.Products)
+ .ToList();
+ IsCategories = !IsProduct && Categories?.Count >= 1;
+ }
+
+ return Page();
+ }
+} \ No newline at end of file
diff --git a/src/Pages/SalesTerms.cshtml b/src/Pages/SalesTerms.cshtml
new file mode 100644
index 0000000..7c48bff
--- /dev/null
+++ b/src/Pages/SalesTerms.cshtml
@@ -0,0 +1,9 @@
+@page "/vilkår"
+@model VSH.Pages.SalesTerms
+@{
+ ViewData["Title"] = "Salgsvilkår";
+}
+
+<div class="container py-5 dynamic-content">
+ @Html.Raw(Model.TermsPageHtml)
+</div> \ No newline at end of file
diff --git a/src/Pages/SalesTerms.cshtml.cs b/src/Pages/SalesTerms.cshtml.cs
new file mode 100644
index 0000000..fe58839
--- /dev/null
+++ b/src/Pages/SalesTerms.cshtml.cs
@@ -0,0 +1,25 @@
+using System.Linq;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.EntityFrameworkCore;
+using VSH.Data;
+using VSH.Data.Enums;
+
+namespace VSH.Pages;
+
+public class SalesTerms : PageModel
+{
+ private readonly MainDbContext _context;
+
+ public SalesTerms(MainDbContext context) {
+ context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
+ _context = context;
+ }
+
+ public string TermsPageHtml { get; set; }
+
+ public void OnGet() {
+ TermsPageHtml = _context.Documents.OrderBy(c => c.Created)
+ .LastOrDefault(c => c.Type == DocumentType.SALES_TERMS)
+ ?.Content;
+ }
+} \ No newline at end of file
diff --git a/src/Pages/Shared/_AdminLayout.cshtml b/src/Pages/Shared/_AdminLayout.cshtml
new file mode 100644
index 0000000..d352928
--- /dev/null
+++ b/src/Pages/Shared/_AdminLayout.cshtml
@@ -0,0 +1,114 @@
+@using VSH.Data.Miscellaneous
+@using Microsoft.Extensions.Options
+@using Microsoft.Extensions.Configuration
+@using VSH.Utilities
+@inject IOptions<AppSettings.GeneralConfiguration> Options;
+@inject IConfiguration Configuration;
+<!DOCTYPE html>
+<html lang="no">
+<head>
+ <meta charset="utf-8"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
+ <link rel="manifest" href="/manifest.json">
+ <link rel="stylesheet" href="~/dist/backbundle.css" asp-append-version="true">
+ @await RenderSectionAsync("Head", required: false)
+ <title>@ViewData["Title"] - Kontoret - @Options.Value.StoreName</title>
+</head>
+<body>
+
+<div class="container my-3">
+ <div class="row">
+ <div class="col">
+ <div class="d-flex mb-3">
+ <div class="flex-grow-1">
+ <h2>@Options.Value.ShortStoreName</h2>
+ </div>
+ <div class="dropdown" id="account-dropdown">
+ <button class="dropdown-toggle btn btn-light" type="button" id="account-dropdown-btn" data-bs-toggle="dropdown" aria-expanded="false">
+ <span class="d-none d-lg-inline">@Context.User.Identity?.Name</span>
+ <span class="d-inline d-lg-none">
+ <i class="bi bi-person fs-3"></i>
+ </span>
+ </button>
+ <div class="dropdown-menu dropdown-menu-right" aria-labelledby="account-dropdown-btn">
+ <a href="/" title="Gå til forsiden" class="dropdown-item">Gå til forsiden</a>
+ <span class="dropdown-item open-update-password-modal cursor-pointer">Endre passord</span>
+ <hr class="dropdown-divider">
+ <span class="text-danger dropdown-item logout-btn cursor-pointer">Logg ut</span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div style="height: 52px;overflow-y: hidden">
+ <div style="overflow: auto hidden">
+ <ul class="nav nav-tabs" role="tablist" style="flex-wrap: nowrap;">
+ <li class="nav-item" role="presentation">
+ @if (Context.Request.Path.Value?.StartsWith("/kontoret/produkter") ?? false) {
+ <a class="nav-link active" href="/kontoret/produkter" role="tab">Produkter</a>
+ } else {
+ <a class="nav-link" href="/kontoret/produkter" role="tab">Produkter</a>
+ }
+ </li>
+ <li class="nav-item" role="presentation">
+ @if (Context.Request.Path.Value?.StartsWith("/kontoret/bestillinger") ?? false) {
+ <a class="nav-link active" href="/kontoret/bestillinger" role="tab">Bestillinger</a>
+ } else {
+ <a class="nav-link" href="/kontoret/bestillinger" role="tab">Bestillinger</a>
+ }
+ </li>
+ <li class="nav-item" role="presentation">
+ @if (Context.Request.Path.Value?.StartsWith("/kontoret/dokumenter") ?? false) {
+ <a class="nav-link active" href="/kontoret/dokumenter" role="tab">Dokumenter</a>
+ } else {
+ <a class="nav-link" href="/kontoret/dokumenter" role="tab">Dokumenter</a>
+ }
+ </li>
+ </ul>
+ </div>
+ </div>
+
+ <script>
+ if (window.innerWidth < 768) {
+ document.querySelector(".nav").style.paddingBottom = "50px";
+ document.querySelector(".nav").className = "nav nav-pills";
+ }
+ </script>
+
+ <main class="py-3">
+ @RenderBody()
+ </main>
+</div>
+
+<div class="modal" tabindex="-1" id="update-password-modal">
+ <div class="modal-dialog modal-sm">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title" id="product-modal-title">Endre passord</h5>
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+ </div>
+ <div class="modal-body">
+ <form onsubmit="return false">
+ <fieldset>
+ <label for="input-new-password" class="form-label mb-2">Nytt passord</label>
+ <input class="form-control" type="password" id="input-new-password" minlength="6" min="6" placeholder="Minst 6 karakterer" required>
+ </fieldset>
+ </form>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Avbryt</button>
+ <button type="button" class="btn btn-primary" id="submit-new-password-form">
+ <span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
+ <span class="text">Lagre</span>
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<span id="version-text" style="position: absolute; bottom: 0; right: 0">@Configuration.GetVersion()</span>
+
+<script src="~/dist/backbundle.min.js" asp-append-version="true"></script>
+@await RenderSectionAsync("Scripts", required: false)
+</body>
+</html> \ No newline at end of file
diff --git a/src/Pages/Shared/_PublicLayout.cshtml b/src/Pages/Shared/_PublicLayout.cshtml
new file mode 100644
index 0000000..d3280dd
--- /dev/null
+++ b/src/Pages/Shared/_PublicLayout.cshtml
@@ -0,0 +1,152 @@
+@using VSH.Data.Miscellaneous
+@using Microsoft.Extensions.Options
+@using Microsoft.Extensions.Localization
+@using IOL.Helpers
+@inject IOptions<AppSettings.GeneralConfiguration> Options;
+@inject IStringLocalizer<SharedPageResources> Localizer;
+@{
+ var host = Context.Request.GetRequestHost();
+ var currentUrl = host + Context.Request.Path.Value;
+ const string CURRENT_CULTURE = "nn";
+ var openGraphData = ViewData["open_graph"] as OpenGraphData;
+}
+<!DOCTYPE html>
+<html lang="@CURRENT_CULTURE">
+<head>
+ <meta charset="utf-8"/>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+ <meta name="description" content="@(openGraphData?.Description ?? Options.Value.DefaultDescription)"/>
+ <meta name="geo.region" content="NO"/>
+ <meta name="geo.placename" content="Vinje"/>
+ <meta name="geo.position" content="59.621963;7.82424"/>
+ <meta name="ICBM" content="59.621963, 7.82424"/>
+ <meta property="og:type" content="@(openGraphData?.Type ?? "website")"/>
+ <meta property="og:locale" content="@(openGraphData?.Locale ?? CURRENT_CULTURE)"/>
+ <meta property="og:title" content="@(openGraphData?.Title ?? ViewData["Title"])"/>
+ <meta property="og:url" content="@(openGraphData?.Url ?? currentUrl)"/>
+ <meta property="og:description" content="@(openGraphData?.Description ?? Options.Value.DefaultDescription)"/>
+ <meta property="og:site_name" content="@(openGraphData?.SiteName ?? Options.Value.StoreName)"/>
+ <meta property="og:image" content="@(openGraphData?.Image ?? (host + "/assets/profile/og_default.png"))"/>
+ <link rel="stylesheet" href="~/dist/frontbundle.css" asp-append-version="true">
+ @await RenderSectionAsync("Head", required: false)
+ <title>@ViewData["Title"] - @Options.Value.StoreName</title>
+</head>
+<body class="d-flex min-vh-100 flex-column">
+
+<nav class="navbar fixed-top navbar-expand-lg user-select-none bg-white">
+ <a class="navbar-brand ps-3" href="/">
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 195.32 48.63">
+ <defs>
+ <style>.cls-logo-1{fill:none;stroke:#ee741e;stroke-miterlimit:10;stroke-width:3px}.cls-logo-2{fill:#ee741e}</style>
+ </defs>
+ <path class="cls-logo-1"
+ d="M24 1.5h167.33a2.49 2.49 0 012.49 2.5v21.72a21.39 21.39 0 01-21.39 21.39H4a2.49 2.49 0 01-2.5-2.5V24A22.5 22.5 0 0124 1.5z"/>
+ <path class="cls-logo-2"
+ d="M244.67 287.43h2.21l2.9 9.27 2.89-9.27h2.21l-4.21 12.78h-1.79zM256.31 287.43h2.1v2.1h-2.1zm0 3.65h2.1v9.13h-2.1zM260.89 291.08H263v9.13h-2.1zm5.41 3.6a1.75 1.75 0 00-.44-1.27 1.66 1.66 0 00-1.25-.45 1.61 1.61 0 00-1.19.42 1.56 1.56 0 00-.43 1.18l-.18-1.89a3.21 3.21 0 011-1.28 2.54 2.54 0 011.48-.44 2.82 2.82 0 012.27 1 4.25 4.25 0 01.8 2.75v5.54h-2.1zM269.72 301.9h.78a.58.58 0 00.45-.18.78.78 0 00.16-.51v-10.13h2.1v10.42a2.51 2.51 0 01-.59 1.78 2.12 2.12 0 01-1.64.64h-1.26zm1.37-14.47h2.13v2.1h-2.13zM278.3 300.34l-.91-.48a3.24 3.24 0 01-1.4-1.39 4.73 4.73 0 01-.48-2.22v-1a5.26 5.26 0 01.46-2.31 3.3 3.3 0 011.35-1.46 4.23 4.23 0 012.12-.5 3.4 3.4 0 012 .59 3.62 3.62 0 011.26 1.69 7.32 7.32 0 01.44 2.67v.6h-6.2V295h4.25v-.1a2.59 2.59 0 00-.54-1.48 1.51 1.51 0 00-1.2-.53 1.88 1.88 0 00-1.47.59 2.53 2.53 0 00-.52 1.69v1.16a2.15 2.15 0 00.56 1.59 2.19 2.19 0 001.59.56 2.85 2.85 0 001-.2 2.92 2.92 0 00.91-.55l1.38 1.27a5 5 0 01-1.56 1 4.52 4.52 0 01-1.74.36zM288 300.34l-.73-.15a6.67 6.67 0 01-1.39-.46 5.07 5.07 0 01-1.16-.73l1.27-1.58a5.72 5.72 0 001.42.75 4.2 4.2 0 001.41.25 3.18 3.18 0 001.46-.26.8.8 0 00.49-.75.66.66 0 00-.24-.56 1.34 1.34 0 00-.62-.26 10.1 10.1 0 00-1.05-.14h-.62a9.26 9.26 0 01-1.57-.29 2 2 0 01-1-.73 2.46 2.46 0 01-.42-1.54 2.84 2.84 0 01.42-1.58 2.51 2.51 0 011.22-1 5.28 5.28 0 012-.33 6.92 6.92 0 011.37.14 7 7 0 011.28.39 6.53 6.53 0 011.15.65l-1.25 1.53a5.57 5.57 0 00-1.3-.59 4.47 4.47 0 00-1.27-.2 2.8 2.8 0 00-1.26.23.78.78 0 00-.43.71.52.52 0 00.24.46 1.64 1.64 0 00.59.21c.24 0 .58.08 1 .12h.4a11.1 11.1 0 011.68.29 2.28 2.28 0 011.13.77 2.65 2.65 0 01.47 1.68 2.92 2.92 0 01-.44 1.63 2.7 2.7 0 01-1.31 1 5.71 5.71 0 01-2.12.34zM299.78 291.08h2.13l-3.43 9.13H297l-3.43-9.13h2.13l2.06 6.12zM303.43 287.43h2.09v2.1h-2.09zm0 3.65h2.09v9.13h-2.09zM308 291.08h2.1v9.13H308zm5.41 3.6a1.75 1.75 0 00-.44-1.27 1.68 1.68 0 00-1.25-.45 1.64 1.64 0 00-1.2.42 1.59 1.59 0 00-.42 1.18l-.18-1.89a3.21 3.21 0 011-1.28 2.54 2.54 0 011.48-.44 2.78 2.78 0 012.26 1 4.19 4.19 0 01.81 2.75v5.54h-2.1zM319.23 299.9a2.73 2.73 0 01-1.06-1.31 5.14 5.14 0 01-.37-2.07v-1.74a5.45 5.45 0 01.36-2.08 2.82 2.82 0 011-1.31 3 3 0 011.66-.46 2.49 2.49 0 011.41.43 3 3 0 011 1.22l-.18 1.94a2.06 2.06 0 00-.18-.9 1.39 1.39 0 00-.54-.56 1.72 1.72 0 00-.85-.19 1.52 1.52 0 00-1.22.51 2.17 2.17 0 00-.43 1.42v1.72a2.12 2.12 0 00.43 1.41 1.54 1.54 0 001.22.49 1.62 1.62 0 00.85-.2 1.39 1.39 0 00.54-.56 2 2 0 00.18-.89l.12 2a2.39 2.39 0 01-2.33 1.59 3 3 0 01-1.61-.46zm.93 4l-.84-.39a3.06 3.06 0 01-1.3-1.07l1.42-1.3a2.18 2.18 0 00.78.64 2.33 2.33 0 001 .22 2 2 0 001.41-.49 1.79 1.79 0 00.52-1.38v-9.07h2.1v8.85a4.65 4.65 0 01-.47 2.16 3.11 3.11 0 01-1.37 1.36 4.67 4.67 0 01-2.17.47zM330.3 300.34l-.91-.48a3.19 3.19 0 01-1.4-1.39 4.73 4.73 0 01-.48-2.22v-1a5.26 5.26 0 01.46-2.31 3.22 3.22 0 011.34-1.46 4.29 4.29 0 012.12-.5 3.38 3.38 0 012 .59 3.57 3.57 0 011.27 1.69 7.33 7.33 0 01.43 2.67v.6h-6.19V295h4.24v-.1a2.52 2.52 0 00-.53-1.48 1.51 1.51 0 00-1.21-.53 1.84 1.84 0 00-1.46.59 2.48 2.48 0 00-.52 1.69v1.16a1.95 1.95 0 002.14 2.15 2.86 2.86 0 001-.2 3 3 0 00.91-.55l1.39 1.27a5.19 5.19 0 01-1.56 1 4.53 4.53 0 01-1.75.36zM337.42 291.08h2.1v9.13h-2.1zm5.41 3.6a1.75 1.75 0 00-.44-1.27 1.68 1.68 0 00-1.25-.45 1.62 1.62 0 00-1.2.42 1.59 1.59 0 00-.42 1.18l-.18-1.89a3.21 3.21 0 011-1.28 2.54 2.54 0 011.48-.44 2.8 2.8 0 012.26 1 4.19 4.19 0 01.81 2.75v5.54h-2.1z"
+ transform="translate(-234.32 -270.82)"/>
+ <path class="cls-logo-1"
+ d="M363.62 271.28c-.58 1.89-1.77 5.38-4.09 11.1-3.92 9.68-9.44 15.37-7.86 21.65s5.65 9.4 14.19 12c2.49.77 4.85 1.41 7 1.95"
+ transform="translate(-234.32 -270.82)"/>
+ <path class="cls-logo-2"
+ d="M363.63 287.43h2.1v12.78h-2.1zm1.11 5.46H372v2h-7.27zm6-5.46h2.1v12.78h-2.1zM376 299.64a2.71 2.71 0 01-.78-2.12 2.5 2.5 0 01.79-2 3.56 3.56 0 012.37-.68h2.44l.13 1.63h-2.55a1.41 1.41 0 00-.94.27 1 1 0 00-.31.81.94.94 0 00.41.84 2.12 2.12 0 001.22.28 3.76 3.76 0 001.49-.22.71.71 0 00.48-.68l.19 1.3a1.59 1.59 0 01-.52.72 2.51 2.51 0 01-.9.43 4.28 4.28 0 01-1.16.15 3.47 3.47 0 01-2.36-.73zm4.74-5.22a1.53 1.53 0 00-.45-1.18 1.82 1.82 0 00-1.28-.43 3.32 3.32 0 00-1 .17 3.2 3.2 0 00-.92.47l-1.4-1.18a3.52 3.52 0 011.41-1 5.22 5.22 0 011.9-.27 4.61 4.61 0 012 .4 2.9 2.9 0 011.26 1.16 3.65 3.65 0 01.44 1.83v5.87h-1.95zM385.25 291.08h2.1v9.13h-2.1zm5.4 3.6a1.75 1.75 0 00-.44-1.27A1.66 1.66 0 00389 293a1.61 1.61 0 00-1.19.42 1.59 1.59 0 00-.42 1.18l-.19-1.89a3.38 3.38 0 011-1.28 2.56 2.56 0 011.48-.44 2.81 2.81 0 012.27 1 4.25 4.25 0 01.8 2.75v5.54h-2.1zM396.47 299.9a2.81 2.81 0 01-1.07-1.31 5.33 5.33 0 01-.36-2.07v-1.74a5.45 5.45 0 01.36-2.08 2.82 2.82 0 011.05-1.31 3 3 0 011.65-.46 2.55 2.55 0 011.42.43 3.17 3.17 0 011 1.22l-.19 1.94a2.06 2.06 0 00-.18-.9 1.27 1.27 0 00-.54-.56 1.7 1.7 0 00-.85-.19 1.5 1.5 0 00-1.21.51 2.11 2.11 0 00-.43 1.42v1.72a2.07 2.07 0 00.43 1.41 1.52 1.52 0 001.21.49 1.6 1.6 0 00.85-.2 1.27 1.27 0 00.54-.56 2 2 0 00.18-.89l.13 2a2.46 2.46 0 01-.88 1.15 2.4 2.4 0 01-1.45.44 2.93 2.93 0 01-1.66-.46zm3.88-12.47h2.11v12.78h-2.11zM407.54 300.34l-.92-.48a3.24 3.24 0 01-1.4-1.39 4.73 4.73 0 01-.48-2.22v-1a5.26 5.26 0 01.46-2.31 3.3 3.3 0 011.35-1.46 4.26 4.26 0 012.12-.5 3.38 3.38 0 012 .59 3.62 3.62 0 011.26 1.69 7.32 7.32 0 01.44 2.67v.6h-6.2V295h4.25v-.1a2.59 2.59 0 00-.54-1.48 1.51 1.51 0 00-1.2-.53 1.88 1.88 0 00-1.47.59 2.53 2.53 0 00-.52 1.69v1.16a2.12 2.12 0 00.57 1.59 2.14 2.14 0 001.58.56 2.85 2.85 0 001-.2 2.92 2.92 0 00.91-.55l1.37 1.29a5 5 0 01-1.56 1 4.48 4.48 0 01-1.74.36zM416.75 297.53a.73.73 0 00.17.51.62.62 0 00.48.18h.6v2h-1.14a2.12 2.12 0 01-1.64-.63 2.53 2.53 0 01-.59-1.78v-10.38h2.1z"
+ transform="translate(-234.32 -270.82)"/>
+ </svg>
+ </a>
+ <button class="navbar-toggler shadow-none border-0 text-primary" type="button" data-bs-toggle="collapse" data-bs-target="#navbar" aria-controls="navbar" aria-expanded="false" aria-label="Toggle navigation">
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-list" viewBox="0 0 16 16">
+ <path fill-rule="evenodd" d="M2.5 11.5A.5.5 0 0 1 3 11h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4A.5.5 0 0 1 3 3h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
+ </svg>
+ </button>
+ <div id="header-cart-button" class="d-flex d-none px-1 h-100 align-items-center cursor-pointer text-primary">
+ <span class="d-none d-md-inline-block px-1">Handlekorg</span>
+ <span class="d-inline-block d-md-none px-1">
+ <svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" fill="currentColor" class="bi bi-basket3" viewBox="0 0 16 16">
+ <path d="M5.757 1.071a.5.5 0 0 1 .172.686L3.383 6h9.234L10.07 1.757a.5.5 0 1 1 .858-.514L13.783 6H15.5a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5H.5a.5.5 0 0 1-.5-.5v-1A.5.5 0 0 1 .5 6h1.717L5.07 1.243a.5.5 0 0 1 .686-.172zM3.394 15l-1.48-6h-.97l1.525 6.426a.75.75 0 0 0 .729.574h9.606a.75.75 0 0 0 .73-.574L15.056 9h-.972l-1.479 6h-9.21z"/>
+ </svg>
+ </span>(<span id="item-count"></span>)
+ </div>
+ <div class="collapse navbar-collapse bg-white px-3" id="navbar">
+ <ul class="navbar-nav me-auto text-uppercase">
+ <li class="nav-item d-none">
+ @if (Context.Request.Path.Value?.StartsWith("/produktar") ?? false) {
+ <a href="/produktar" class="nav-link active" title="@Localizer["Gå til /produktar"]" aria-current="page">@Localizer["Produktar"]</a>
+ } else {
+ <a href="/produktar" class="nav-link" title="@Localizer["Gå til /produktar"]">@Localizer["Produktar"]</a>
+ }
+ </li>
+ <li class="nav-item">
+ @if (Context.Request.Path.Value?.StartsWith("/leverandørar") ?? false) {
+ <a href="/leverandørar" class="nav-link active" title="@Localizer["Gå til /leverandørar"]" aria-current="page">@Localizer["Leverandørar"]</a>
+ } else {
+ <a href="/leverandørar" class="nav-link" title="@Localizer["Gå til /leverandørar"]">@Localizer["Leverandørar"]</a>
+ }
+ </li>
+ <li class="nav-item">
+ @if (Context.Request.Path.Value?.StartsWith("/om-oss") ?? false) {
+ <a href="/om-oss" class="nav-link active" title="@Localizer["Gå til /om-oss"]" aria-current="page">@Localizer["Om oss"]</a>
+ } else {
+ <a href="/om-oss" class="nav-link" title="@Localizer["Gå til /om-oss"]">@Localizer["Om oss"]</a>
+ }
+ </li>
+ <li class="nav-item">
+ <a href="/#kontakt" class="nav-link" title="@Localizer["Gå til kontaktinformasjon"]">@Localizer["Kontakt oss"]</a>
+ </li>
+ @if (User.Identity?.IsAuthenticated ?? false) {
+ <li class="nav-item">
+ <a href="/kontoret" class="nav-link" title="@Localizer["Gå til kontoret"]">
+ Kontoret
+ </a>
+ </li>
+ }
+ </ul>
+ </div>
+</nav>
+
+<main class="flex-1" id="body-wrapper">
+
+ @RenderBody()
+
+</main>
+
+<footer>
+ <div class="container py-5">
+ <div class="row">
+ <div class="col-sm-6">
+ <span class="text-uppercase">&copy; @Options.Value.StoreName</span>
+ | <a href="/personvern">@Localizer["Personvernerklæring"]</a>
+ | <a href="/vilkår">@Localizer["Salsvilkår"]</a>
+ | <a href="https://www.facebook.com/VinjesvingenHandel">Facebook</a>
+ </div>
+ </div>
+ </div>
+</footer>
+
+<div id="cart-modal" class="modal modal-right" tabindex="-1" role="dialog">
+ <div class="modal-dialog modal-dialog-aside" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title">@Localizer["Handlekorg"]</h5>
+ <button type="button" class="btn-close close" data-bs-dismiss="modal" aria-label="@Localizer["Lukk"]"></button>
+ </div>
+ <div class="modal-body">
+ <div id="product-list"></div>
+ </div>
+ <div class="modal-footer flex-column align-items-end">
+ <div id="quote" class="mb-3 mb-md-4">
+ <span class="h3">@Localizer["I alt"]: <span id="total"></span></span>
+ </div>
+
+ <div class="w-100">
+ <button type="button" class="btn btn-primary btn-lg submit-cart w-100">@Localizer["Gå til kassa"]</button>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script src="~/dist/frontbundle.min.js" asp-append-version="true"></script>
+@await RenderSectionAsync("Scripts", required: false)
+
+</body>
+</html>
diff --git a/src/Pages/Status.cshtml b/src/Pages/Status.cshtml
new file mode 100644
index 0000000..d0e2ad1
--- /dev/null
+++ b/src/Pages/Status.cshtml
@@ -0,0 +1,136 @@
+@page "{orderReference}"
+@using VSH.Data.Enums
+@using VSH.Utilities
+@using System.Globalization
+@using IOL.Helpers
+@model VSH.Pages.Status
+
+@{
+ string title;
+ if (Model.CurrentOrder == default) {
+ title = "Fant ikkje ordren";
+ } else {
+ title = Model.CurrentOrder.Status switch {
+ OrderStatus.CANCELLED => "Kansellert bestilling",
+ OrderStatus.FAILED => "Feila bestilling",
+ OrderStatus.COMPLETED => "Fullført bestilling",
+ OrderStatus.AWAITING_INVOICE
+ or OrderStatus.AWAITING_VIPPS
+ or OrderStatus.IN_PROGRESS => "Ventar på betaling",
+ var _ => "Uventa feil"
+ };
+ }
+ ViewData["Title"] = title;
+}
+<div class="container py-5">
+ @if (Model.CurrentOrder != default) {
+ <div class="row">
+ <div class="col-12 col-md-4">
+ <div class="row mb-3">
+ <h2>Din bestilling</h2>
+ <hr>
+ <p>
+ <span class="text-bold">Status:</span>
+ @(title)
+ </p>
+ <p>
+ <span class="text-bold">Betalingsmetode:</span>
+ @(EnumName.ForPaymentType(Model.CurrentOrder.PaymentType))
+ @if (Model.CurrentOrder.PaymentType == OrderPaymentType.INVOICE_BY_EMAIL) {
+ <small>Du får tilsendt faktura til din e-postadresse</small>
+ }
+ </p>
+ <p>
+ <span class="text-bold">Referanse:</span>
+ @Model.CurrentOrder.OrderReference
+ </p>
+ <p>
+ <span class="text-bold">Dato:</span>
+ @Model.CurrentOrder.Created.ToOsloTimeZone().ToString("dd.MM.yyyy HH:mm", new CultureInfo("nb-NO"))
+ </p>
+
+ @if (!Model.CurrentOrder.Comment.IsNullOrWhiteSpace()) {
+ <p>
+ <span class="text-bold">Øvrig informasjon:</span>
+ @Model.CurrentOrder.Comment
+ </p>
+ }
+
+ </div>
+ <div class="row">
+ <h3>Kontaktinformasjon</h3>
+ <hr>
+ <p>
+ <span class="text-bold">Namn:</span>
+ @Model.CurrentOrder.ContactInfo.Name
+ </p>
+
+ @if (!Model.CurrentOrder.ContactInfo.EmailAddress.IsNullOrWhiteSpace()) {
+ <p>
+ <span class="text-bold">E-postadresse:</span>
+ @Model.CurrentOrder.ContactInfo.EmailAddress
+ </p>
+ }
+
+ @if (!Model.CurrentOrder.ContactInfo.PhoneNumber.IsNullOrWhiteSpace()) {
+ <p>
+ <span class="text-bold">Telefonnummer:</span>
+ @Model.CurrentOrder.ContactInfo.PhoneNumber
+ </p>
+ }
+ </div>
+ <div class="row">
+ <h3>Spørsmål?</h3>
+ <hr>
+ <p><a href="/#kontakt">Ta gjerne kontakt</a> hvis du har spørsmål vedrørande ordren din.</p>
+ </div>
+ </div>
+ <div class="col-12 col-md-8">
+ <div class="row">
+ <h2>Produktar</h2>
+ <hr>
+ <div class="h-100">
+ @foreach (var product in Model.CurrentOrderProducts) {
+ <div class="border-0 my-3 d-flex align-items-center">
+ <a href="@product.DbProdcut.WebPath()">
+ <img src="@product.DbProdcut.GetPrimaryImage().WebPath" class="blur-up lazyload w-150px object-fit-contain" alt="">
+ </a>
+ <div class="p-2 w-100">
+ <a href="@product.DbProdcut.WebPath()" class="h3">@product.DbProdcut.Name</a>
+ <div class="d-flex flex-column align-items-end w-100">
+ <span>Antall: <span>@product.OrderProduct.NumberOfItems</span></span>
+ <span class="fs-4">
+ Totalt:
+ <span>
+ @product.OrderProduct.Total().ToString("N", new NumberFormatInfo {
+ CurrencyDecimalDigits = 2
+ }),-
+ </span>
+ </span>
+ </div>
+ </div>
+ </div>
+ }
+ </div>
+ <div class="d-flex float-right flex-column">
+ <div class="d-flex flex-column">
+ <span class="h2">
+ Totalt: @Model.CurrentOrder.Total().ToString("N", new NumberFormatInfo {
+ CurrencyDecimalDigits = 2
+ }),-
+ </span>
+ <span>
+ Av dei MVA: @Model.CurrentOrder.Tax().ToString("N", new NumberFormatInfo {
+ CurrencyDecimalDigits = 2
+ }),-
+ </span>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ } else {
+ <h2>Vi fant ikkje din ordre</h2>
+ <p>Ver vennleg og <a href="/#kontakt">kontakt oss</a> hvis du meiner dette er ein feil.</p>
+ }
+</div>
diff --git a/src/Pages/Status.cshtml.cs b/src/Pages/Status.cshtml.cs
new file mode 100644
index 0000000..ed15120
--- /dev/null
+++ b/src/Pages/Status.cshtml.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.EntityFrameworkCore;
+using VSH.Data;
+using VSH.Data.Database;
+
+namespace VSH.Pages;
+
+public class Status : PageModel
+{
+ private readonly MainDbContext _context;
+ public Order CurrentOrder { get; private set; }
+ public List<StatusProduct> CurrentOrderProducts { get; }
+
+ public Status(MainDbContext context) {
+ _context = context;
+ CurrentOrderProducts = new List<StatusProduct>();
+ }
+
+ public ActionResult OnGet(string orderReference) {
+ try {
+ CurrentOrder = _context.Orders.SingleOrDefault(o => o.OrderReference == orderReference);
+ if (CurrentOrder == default) return Page();
+
+ foreach (var orderProduct in CurrentOrder.Products) {
+ var dbProduct = _context.Products.Include(c => c.Category)
+ .SingleOrDefault(p => p.Id == orderProduct.Id);
+ if (dbProduct == default) continue;
+ CurrentOrderProducts.Add(new StatusProduct(dbProduct, orderProduct));
+ }
+
+ return Page();
+ } catch (Exception e) {
+ Console.WriteLine(e);
+ }
+
+ return Redirect("/errors/500");
+ }
+
+ public class StatusProduct
+ {
+ public StatusProduct(Product dbProdcut, OrderProduct orderProduct) {
+ DbProdcut = dbProdcut;
+ OrderProduct = orderProduct;
+ }
+
+ public Product DbProdcut { get; }
+ public OrderProduct OrderProduct { get; }
+ }
+} \ No newline at end of file
diff --git a/src/Pages/_ViewImports.cshtml b/src/Pages/_ViewImports.cshtml
new file mode 100644
index 0000000..3a327c4
--- /dev/null
+++ b/src/Pages/_ViewImports.cshtml
@@ -0,0 +1,3 @@
+@using VSH
+@namespace VSH.Pages
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
diff --git a/src/Pages/_ViewStart.cshtml b/src/Pages/_ViewStart.cshtml
new file mode 100644
index 0000000..45bfaa9
--- /dev/null
+++ b/src/Pages/_ViewStart.cshtml
@@ -0,0 +1,3 @@
+@{
+ Layout = "_PublicLayout";
+}