Create local business
This commit is contained in:
parent
7abf25345f
commit
a727a78bcb
114
client/dist/app.js
vendored
114
client/dist/app.js
vendored
@ -8,6 +8,9 @@ form legend {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
form.inline div {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
form > div {
|
form > div {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
@ -127,6 +130,9 @@ customElements.define("form-navigation", class extends HTMLElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
input {
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
input.hidden {
|
input.hidden {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
@ -138,17 +144,9 @@ customElements.define("form-navigation", class extends HTMLElement {
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
`, c.querySelector("#prev").addEventListener("click", (a)=>{
|
`, c.querySelector("#prev").addEventListener("click", (a)=>{
|
||||||
a.stopPropagation(), a.preventDefault(), this.dispatchEvent(new CustomEvent("form:prev", {
|
a.stopPropagation(), a.preventDefault(), this.prev();
|
||||||
bubbles: !0,
|
|
||||||
composed: !0,
|
|
||||||
detail: this.parentElement
|
|
||||||
}));
|
|
||||||
}), c.querySelector("#next").addEventListener("click", (a)=>{
|
}), c.querySelector("#next").addEventListener("click", (a)=>{
|
||||||
a.stopPropagation(), a.preventDefault(), this.dispatchEvent(new CustomEvent("form:next", {
|
a.stopPropagation(), a.preventDefault(), this.next();
|
||||||
bubbles: !0,
|
|
||||||
composed: !0,
|
|
||||||
detail: this.parentElement
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
attributeChangedCallback(b, c, d) {
|
attributeChangedCallback(b, c, d) {
|
||||||
@ -160,6 +158,20 @@ customElements.define("form-navigation", class extends HTMLElement {
|
|||||||
this[S].querySelector("#prev").className = "hidden" === d ? "hidden" : "";
|
this[S].querySelector("#prev").className = "hidden" === d ? "hidden" : "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
next() {
|
||||||
|
this.dispatchEvent(new CustomEvent("form:next", {
|
||||||
|
bubbles: !0,
|
||||||
|
composed: !0,
|
||||||
|
detail: this.parentElement
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
prev() {
|
||||||
|
this.dispatchEvent(new CustomEvent("form:prev", {
|
||||||
|
bubbles: !0,
|
||||||
|
composed: !0,
|
||||||
|
detail: this.parentElement
|
||||||
|
}));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
customElements.define("local-service", class extends HTMLElement {
|
customElements.define("local-service", class extends HTMLElement {
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
@ -372,17 +384,19 @@ customElements.define("ow-account", class extends HTMLElement {
|
|||||||
#form > * {
|
#form > * {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
:host([mode="login"]) login-form, :host([mode="login"]) #switch-register {
|
:host([mode="login"]) #form > login-form, :host([mode="login"]) #switch-register {
|
||||||
display: block;
|
display: block !important;
|
||||||
}
|
}
|
||||||
:host([mode="register"]) register-form, :host([mode="register"]) #switch-login {
|
:host([mode="register"]) #form > register-form, :host([mode="register"]) #switch-login {
|
||||||
display: block;
|
display: block !important;
|
||||||
}
|
}
|
||||||
#display {
|
#display {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
:host([mode="display"]) #display { display: block; }
|
:host([mode="display"]) #display { display: block; }
|
||||||
:host([mode="display"]) #form { display: none; }
|
:host([mode="display"]) #form { display: none; }
|
||||||
|
:host([mode="form"]) #form,
|
||||||
|
:host([mode="login"]) #form { display: block; }
|
||||||
|
|
||||||
a{
|
a{
|
||||||
display: block;
|
display: block;
|
||||||
@ -406,6 +420,7 @@ customElements.define("ow-account", class extends HTMLElement {
|
|||||||
<a>Masz konta? Zaloguj się</a>
|
<a>Masz konta? Zaloguj się</a>
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article id="display">
|
<article id="display">
|
||||||
<div>
|
<div>
|
||||||
<input id="id" name="id" readonly type="hidden" />
|
<input id="id" name="id" readonly type="hidden" />
|
||||||
@ -658,13 +673,20 @@ customElements.define("price-input", class extends HTMLElement {
|
|||||||
${FORM_STYLE}
|
${FORM_STYLE}
|
||||||
</style>
|
</style>
|
||||||
<div id="view">
|
<div id="view">
|
||||||
<input id="price" type="number" min="0.00" max="10000.00" step="0.01" />
|
<input
|
||||||
|
id="price" type="number" min="0.00" max="10000.00" step="0.01"
|
||||||
|
placeholder="Cena, np: 12.23"
|
||||||
|
/>
|
||||||
<span id="currency"></span>
|
<span id="currency"></span>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
let d = c.querySelector("#price");
|
||||||
|
d.addEventListener("change", (a)=>{
|
||||||
|
a.stopPropagation(), this.value = d.value;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
this[S].querySelector("#currency").textContent = this.currency;
|
this[S].querySelector("#currency").textContent = this.currency, this[S].querySelector("#price").value = this.value;
|
||||||
}
|
}
|
||||||
attributeChangedCallback(b, c, d) {
|
attributeChangedCallback(b, c, d) {
|
||||||
if (c === d) return;
|
if (c === d) return;
|
||||||
@ -681,6 +703,9 @@ customElements.define("price-input", class extends HTMLElement {
|
|||||||
break;
|
break;
|
||||||
case "readonly":
|
case "readonly":
|
||||||
d ? e.setAttribute("readonly", "readonly") : e.removeAttribute("readonly");
|
d ? e.setAttribute("readonly", "readonly") : e.removeAttribute("readonly");
|
||||||
|
break;
|
||||||
|
case "name":
|
||||||
|
this.setAttribute("name", d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
get value() {
|
get value() {
|
||||||
@ -721,7 +746,7 @@ customElements.define("register-basic-form", class extends PseudoForm {
|
|||||||
<form id="step-1">
|
<form id="step-1">
|
||||||
<div>
|
<div>
|
||||||
<label>Login</label>
|
<label>Login</label>
|
||||||
<input id="login" name="login" placeholder="Login" type="text" required />
|
<input id="login" name="login" placeholder="Login" type="text" required autofocus />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>E-Mail</label>
|
<label>E-Mail</label>
|
||||||
@ -736,11 +761,7 @@ customElements.define("register-basic-form", class extends PseudoForm {
|
|||||||
`;
|
`;
|
||||||
let d = c.querySelector("form");
|
let d = c.querySelector("form");
|
||||||
d.addEventListener("submit", (a)=>{
|
d.addEventListener("submit", (a)=>{
|
||||||
a.preventDefault(), a.stopPropagation(), this.dispatchEvent(new CustomEvent("form:next", {
|
a.preventDefault(), a.stopPropagation(), c.querySelector("form-navigation").next();
|
||||||
bubbles: !0,
|
|
||||||
composed: !0,
|
|
||||||
detail: d
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -771,8 +792,13 @@ customElements.define("register-item-form-row", class extends PseudoForm {
|
|||||||
* { font-family: 'Noto Sans', sans-serif; }
|
* { font-family: 'Noto Sans', sans-serif; }
|
||||||
${FORM_STYLE}
|
${FORM_STYLE}
|
||||||
|
|
||||||
section {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
min-width: 100px;
|
||||||
|
max-width: 48%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<form class="inline">
|
<form class="inline">
|
||||||
@ -801,8 +827,8 @@ customElements.define("register-item-form-row", class extends PseudoForm {
|
|||||||
}
|
}
|
||||||
get inputs() {
|
get inputs() {
|
||||||
return [
|
return [
|
||||||
this[S].querySelector(".item-name").cloneNode(!0),
|
d(this[S].querySelector(".item-name")),
|
||||||
this[S].querySelector(".item-price").cloneNode(!0),
|
d(this[S].querySelector(".item-price")),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
updateNames() {
|
updateNames() {
|
||||||
@ -822,7 +848,11 @@ customElements.define("register-item-form-row", class extends PseudoForm {
|
|||||||
return super.reportValidity() && this[S].querySelector("price-input").reportValidity();
|
return super.reportValidity() && this[S].querySelector("price-input").reportValidity();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let d = (a)=>{
|
let d = ({ name: a , value: b })=>({
|
||||||
|
name: a,
|
||||||
|
value: b
|
||||||
|
});
|
||||||
|
let d1 = (a)=>{
|
||||||
let b = 0;
|
let b = 0;
|
||||||
for (let c of a.querySelectorAll("register-item-form-row"))c.idx = b++;
|
for (let c of a.querySelectorAll("register-item-form-row"))c.idx = b++;
|
||||||
return b;
|
return b;
|
||||||
@ -856,11 +886,11 @@ customElements.define("register-items-form", class extends PseudoForm {
|
|||||||
<form-navigation></form-navigation>
|
<form-navigation></form-navigation>
|
||||||
</form>
|
</form>
|
||||||
`, this.addEventListener("item:removed", (a)=>{
|
`, this.addEventListener("item:removed", (a)=>{
|
||||||
a.stopPropagation(), d(this);
|
a.stopPropagation(), d1(this);
|
||||||
}), this.addEventListener("form:next", (a)=>{
|
}), this.addEventListener("form:next", (a)=>{
|
||||||
for (let b of this.querySelectorAll("item-form-row"))b.reportValidity() || (a.stopPropagation(), a.preventDefault());
|
for (let b of this.querySelectorAll("item-form-row"))b.reportValidity() || (a.stopPropagation(), a.preventDefault());
|
||||||
}), c.querySelector("#add-item").addEventListener("click", (a)=>{
|
}), c.querySelector("#add-item").addEventListener("click", (a)=>{
|
||||||
a.stopPropagation(), a.preventDefault(), this.appendChild(document.createElement("register-item-form-row")), d(this);
|
a.stopPropagation(), a.preventDefault(), this.appendChild(document.createElement("register-item-form-row")), d1(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
get inputs() {
|
get inputs() {
|
||||||
@ -883,7 +913,7 @@ customElements.define("register-company-form", class extends PseudoForm {
|
|||||||
</style>
|
</style>
|
||||||
<form id="step-2">
|
<form id="step-2">
|
||||||
<div>
|
<div>
|
||||||
<input name="name" placeholder="Nazwa usługi" type="text" required />
|
<input name="name" placeholder="Nazwa usługi" type="text" required autofocus />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>description</label>
|
<label>description</label>
|
||||||
@ -891,7 +921,9 @@ customElements.define("register-company-form", class extends PseudoForm {
|
|||||||
</div>
|
</div>
|
||||||
<form-navigation></form-navigation>
|
<form-navigation></form-navigation>
|
||||||
</form>
|
</form>
|
||||||
`;
|
`, c.querySelector("form").addEventListener("submit", (a)=>{
|
||||||
|
a.preventDefault(), a.stopPropagation(), c.querySelector("form-navigation").next();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
customElements.define("register-submit-form", class extends PseudoForm {
|
customElements.define("register-submit-form", class extends PseudoForm {
|
||||||
@ -905,12 +937,20 @@ customElements.define("register-submit-form", class extends PseudoForm {
|
|||||||
:host { display: block; }
|
:host { display: block; }
|
||||||
* { font-family: 'Noto Sans', sans-serif; }
|
* { font-family: 'Noto Sans', sans-serif; }
|
||||||
${FORM_STYLE}
|
${FORM_STYLE}
|
||||||
|
.item-view {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.item-view > * {
|
||||||
|
min-width: 100px;
|
||||||
|
max-width: 48%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<form id="step-4">
|
<form id="step-4" method="post" action="/register">
|
||||||
<div id="copied">
|
<div id="copied">
|
||||||
<input id="hidden-login" name="login" type="hidden" />
|
<input id="hidden-login" name="login" type="hidden" />
|
||||||
<input id="hidden-email" name="email" type="hidden" />
|
<input id="hidden-email" name="email" type="hidden" />
|
||||||
<input id="hidden-pass" name="pass" type="hidden" />
|
<input id="hidden-pass" name="password" type="hidden" />
|
||||||
<input id="hidden-name" name="name" type="hidden" />
|
<input id="hidden-name" name="name" type="hidden" />
|
||||||
<input id="hidden-description" name="description" type="hidden" />
|
<input id="hidden-description" name="description" type="hidden" />
|
||||||
</div>
|
</div>
|
||||||
@ -951,8 +991,14 @@ customElements.define("register-submit-form", class extends PseudoForm {
|
|||||||
setItems(a) {
|
setItems(a) {
|
||||||
let c = this[S].querySelector("#items");
|
let c = this[S].querySelector("#items");
|
||||||
for (let d of (c.innerHTML = "", a)){
|
for (let d of (c.innerHTML = "", a)){
|
||||||
let e = c.appendChild(document.createElement("div")), [f, g] = d;
|
let e = c.appendChild(document.createElement("div"));
|
||||||
f.setAttribute("readonly", "readonly"), e.appendChild(f), e.appendChild(document.createElement("price-view")).value = g.value, g.setAttribute("readonly", "readonly"), g.setAttribute("type", "hidden"), e.appendChild(g);
|
e.className = "item-view";
|
||||||
|
let [f, g] = d;
|
||||||
|
e.innerHTML = `
|
||||||
|
<input type="text" name="${f.name}" value="${f.value}" readonly />
|
||||||
|
<input type="hidden" name="${g.name}" value="${g.value}" readonly />
|
||||||
|
<price-view value="${g.value}"></price-view>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
set accountType(a) {
|
set accountType(a) {
|
||||||
|
2
client/dist/app.js.map
vendored
2
client/dist/app.js.map
vendored
File diff suppressed because one or more lines are too long
@ -18,6 +18,9 @@ customElements.define('form-navigation', class extends HTMLElement {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
input {
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
input.hidden {
|
input.hidden {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
@ -32,20 +35,12 @@ customElements.define('form-navigation', class extends HTMLElement {
|
|||||||
shadow.querySelector('#prev').addEventListener('click', ev => {
|
shadow.querySelector('#prev').addEventListener('click', ev => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.dispatchEvent(new CustomEvent('form:prev', {
|
this.prev();
|
||||||
bubbles: true,
|
|
||||||
composed: true,
|
|
||||||
detail: this.parentElement
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
shadow.querySelector('#next').addEventListener('click', ev => {
|
shadow.querySelector('#next').addEventListener('click', ev => {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
this.dispatchEvent(new CustomEvent('form:next', {
|
this.next();
|
||||||
bubbles: true,
|
|
||||||
composed: true,
|
|
||||||
detail: this.parentElement
|
|
||||||
}));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,4 +57,20 @@ customElements.define('form-navigation', class extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next() {
|
||||||
|
this.dispatchEvent(new CustomEvent('form:next', {
|
||||||
|
bubbles: true,
|
||||||
|
composed: true,
|
||||||
|
detail: this.parentElement
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
prev() {
|
||||||
|
this.dispatchEvent(new CustomEvent('form:prev', {
|
||||||
|
bubbles: true,
|
||||||
|
composed: true,
|
||||||
|
detail: this.parentElement
|
||||||
|
}));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { S } from "./shared";
|
import { S } from "../shared";
|
||||||
|
|
||||||
customElements.define('ow-nav', class extends HTMLElement {
|
customElements.define('ow-nav', class extends HTMLElement {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { S } from "./shared";
|
import { S } from "../shared";
|
||||||
|
|
||||||
customElements.define('ow-path', class extends HTMLElement {
|
customElements.define('ow-path', class extends HTMLElement {
|
||||||
static get observedAttributes() {
|
static get observedAttributes() {
|
||||||
|
@ -15,17 +15,19 @@ customElements.define('ow-account', class extends HTMLElement {
|
|||||||
#form > * {
|
#form > * {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
:host([mode="login"]) login-form, :host([mode="login"]) #switch-register {
|
:host([mode="login"]) #form > login-form, :host([mode="login"]) #switch-register {
|
||||||
display: block;
|
display: block !important;
|
||||||
}
|
}
|
||||||
:host([mode="register"]) register-form, :host([mode="register"]) #switch-login {
|
:host([mode="register"]) #form > register-form, :host([mode="register"]) #switch-login {
|
||||||
display: block;
|
display: block !important;
|
||||||
}
|
}
|
||||||
#display {
|
#display {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
:host([mode="display"]) #display { display: block; }
|
:host([mode="display"]) #display { display: block; }
|
||||||
:host([mode="display"]) #form { display: none; }
|
:host([mode="display"]) #form { display: none; }
|
||||||
|
:host([mode="form"]) #form,
|
||||||
|
:host([mode="login"]) #form { display: block; }
|
||||||
|
|
||||||
a{
|
a{
|
||||||
display: block;
|
display: block;
|
||||||
@ -49,6 +51,7 @@ customElements.define('ow-account', class extends HTMLElement {
|
|||||||
<a>Masz konta? Zaloguj się</a>
|
<a>Masz konta? Zaloguj się</a>
|
||||||
</section>
|
</section>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<article id="display">
|
<article id="display">
|
||||||
<div>
|
<div>
|
||||||
<input id="id" name="id" readonly type="hidden" />
|
<input id="id" name="id" readonly type="hidden" />
|
||||||
|
@ -25,15 +25,24 @@ customElements.define('price-input', class extends HTMLElement {
|
|||||||
${FORM_STYLE}
|
${FORM_STYLE}
|
||||||
</style>
|
</style>
|
||||||
<div id="view">
|
<div id="view">
|
||||||
<input id="price" type="number" min="0.00" max="10000.00" step="0.01" />
|
<input
|
||||||
|
id="price" type="number" min="0.00" max="10000.00" step="0.01"
|
||||||
|
placeholder="Cena, np: 12.23"
|
||||||
|
/>
|
||||||
<span id="currency"></span>
|
<span id="currency"></span>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const price = shadow.querySelector('#price');
|
||||||
|
price.addEventListener('change', ev => {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this.value = price.value;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
this[S].querySelector('#currency').textContent = this.currency;
|
this[S].querySelector('#currency').textContent = this.currency;
|
||||||
// this[S].querySelector('#price').textContent = this.formatted;
|
this[S].querySelector('#price').value = this.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
attributeChangedCallback(name, oldV, newV) {
|
attributeChangedCallback(name, oldV, newV) {
|
||||||
@ -61,6 +70,7 @@ customElements.define('price-input', class extends HTMLElement {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'name': {
|
case 'name': {
|
||||||
|
this.setAttribute('name', newV);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ customElements.define('register-basic-form', class extends PseudoForm {
|
|||||||
<form id="step-1">
|
<form id="step-1">
|
||||||
<div>
|
<div>
|
||||||
<label>Login</label>
|
<label>Login</label>
|
||||||
<input id="login" name="login" placeholder="Login" type="text" required />
|
<input id="login" name="login" placeholder="Login" type="text" required autofocus />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>E-Mail</label>
|
<label>E-Mail</label>
|
||||||
@ -34,7 +34,7 @@ customElements.define('register-basic-form', class extends PseudoForm {
|
|||||||
form.addEventListener('submit', ev => {
|
form.addEventListener('submit', ev => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
this.dispatchEvent(new CustomEvent('form:next', { bubbles: true, composed: true, detail: form }));
|
shadow.querySelector('form-navigation').next();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -14,7 +14,7 @@ customElements.define('register-company-form', class extends PseudoForm {
|
|||||||
</style>
|
</style>
|
||||||
<form id="step-2">
|
<form id="step-2">
|
||||||
<div>
|
<div>
|
||||||
<input name="name" placeholder="Nazwa usługi" type="text" required />
|
<input name="name" placeholder="Nazwa usługi" type="text" required autofocus />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label>description</label>
|
<label>description</label>
|
||||||
@ -23,5 +23,11 @@ customElements.define('register-company-form', class extends PseudoForm {
|
|||||||
<form-navigation></form-navigation>
|
<form-navigation></form-navigation>
|
||||||
</form>
|
</form>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
shadow.querySelector('form').addEventListener('submit', ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
shadow.querySelector('form-navigation').next();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -25,8 +25,13 @@ customElements.define('register-item-form-row', class extends PseudoForm {
|
|||||||
* { font-family: 'Noto Sans', sans-serif; }
|
* { font-family: 'Noto Sans', sans-serif; }
|
||||||
${ FORM_STYLE }
|
${ FORM_STYLE }
|
||||||
|
|
||||||
section {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
min-width: 100px;
|
||||||
|
max-width: 48%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<form class="inline">
|
<form class="inline">
|
||||||
@ -65,11 +70,10 @@ customElements.define('register-item-form-row', class extends PseudoForm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
get inputs() {
|
get inputs() {
|
||||||
return [
|
return [
|
||||||
this[S].querySelector('.item-name').cloneNode(true),
|
extract(this[S].querySelector('.item-name')),
|
||||||
this[S].querySelector('.item-price').cloneNode(true),
|
extract(this[S].querySelector('.item-price')),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,3 +97,5 @@ customElements.define('register-item-form-row', class extends PseudoForm {
|
|||||||
return super.reportValidity() && this[S].querySelector('price-input').reportValidity();
|
return super.reportValidity() && this[S].querySelector('price-input').reportValidity();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const extract = ({ name, value }) => ({ name, value })
|
||||||
|
@ -11,12 +11,20 @@ customElements.define('register-submit-form', class extends PseudoForm {
|
|||||||
:host { display: block; }
|
:host { display: block; }
|
||||||
* { font-family: 'Noto Sans', sans-serif; }
|
* { font-family: 'Noto Sans', sans-serif; }
|
||||||
${ FORM_STYLE }
|
${ FORM_STYLE }
|
||||||
|
.item-view {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.item-view > * {
|
||||||
|
min-width: 100px;
|
||||||
|
max-width: 48%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<form id="step-4">
|
<form id="step-4" method="post" action="/register">
|
||||||
<div id="copied">
|
<div id="copied">
|
||||||
<input id="hidden-login" name="login" type="hidden" />
|
<input id="hidden-login" name="login" type="hidden" />
|
||||||
<input id="hidden-email" name="email" type="hidden" />
|
<input id="hidden-email" name="email" type="hidden" />
|
||||||
<input id="hidden-pass" name="pass" type="hidden" />
|
<input id="hidden-pass" name="password" type="hidden" />
|
||||||
<input id="hidden-name" name="name" type="hidden" />
|
<input id="hidden-name" name="name" type="hidden" />
|
||||||
<input id="hidden-description" name="description" type="hidden" />
|
<input id="hidden-description" name="description" type="hidden" />
|
||||||
</div>
|
</div>
|
||||||
@ -62,15 +70,14 @@ customElements.define('register-submit-form', class extends PseudoForm {
|
|||||||
host.innerHTML = ``;
|
host.innerHTML = ``;
|
||||||
for (const row of items) {
|
for (const row of items) {
|
||||||
const el = host.appendChild(document.createElement('div'));
|
const el = host.appendChild(document.createElement('div'));
|
||||||
|
el.className = 'item-view';
|
||||||
const [name, price] = row;
|
const [name, price] = row;
|
||||||
|
|
||||||
name.setAttribute('readonly', 'readonly');
|
el.innerHTML = `
|
||||||
el.appendChild(name);
|
<input type="text" name="${name.name}" value="${name.value}" readonly />
|
||||||
|
<input type="hidden" name="${price.name}" value="${price.value}" readonly />
|
||||||
el.appendChild(document.createElement('price-view')).value = price.value;
|
<price-view value="${price.value}"></price-view>
|
||||||
price.setAttribute('readonly', 'readonly');
|
`;
|
||||||
price.setAttribute('type', 'hidden');
|
|
||||||
el.appendChild(price);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,9 @@ form legend {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
form.inline div {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
form > div {
|
form > div {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
|
@ -1,49 +1,49 @@
|
|||||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
|
||||||
CREATE TABLE accounts (
|
CREATE TABLE accounts (
|
||||||
id serial unique not null primary key,
|
id serial unique not null primary key,
|
||||||
login text not null,
|
login text not null,
|
||||||
pass text not null
|
pass text not null
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TYPE "Role" AS ENUM (
|
CREATE TYPE "Role" AS ENUM (
|
||||||
'User',
|
'User',
|
||||||
'Admin'
|
'Admin'
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TYPE "LocalServiceState" AS ENUM (
|
CREATE TYPE "LocalServiceState" AS ENUM (
|
||||||
'Pending',
|
'Pending',
|
||||||
'Approved',
|
'Approved',
|
||||||
'Banned',
|
'Banned',
|
||||||
'Pinned',
|
'Pinned',
|
||||||
'Internal'
|
'Internal'
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE tokens (
|
CREATE TABLE tokens (
|
||||||
id serial unique not null primary key,
|
id serial unique not null primary key,
|
||||||
claims jsonb not null,
|
claims jsonb not null,
|
||||||
iss text not null default 'oswilno', /* issuer */
|
iss text not null default 'oswilno', /* issuer */
|
||||||
sub int references accounts (id), /* subject */
|
sub int references accounts (id), /* subject */
|
||||||
aud text not null default 'public', /* audience */
|
aud text not null default 'public', /* audience */
|
||||||
exp timestamp not null, /* expiration time */
|
exp timestamp not null, /* expiration time */
|
||||||
nbt timestamp not null default now(), /* not before time */
|
nbt timestamp not null default now(), /* not before time */
|
||||||
iat timestamp not null default now(), /* issued at time */
|
iat timestamp not null default now(), /* issued at time */
|
||||||
jti uuid not null unique, /* JWT ID - unique */
|
jti uuid not null unique, /* JWT ID - unique */
|
||||||
role "Role" not null default 'User'
|
role "Role" not null default 'User'
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE local_services (
|
CREATE TABLE local_services (
|
||||||
id serial unique not null primary key,
|
id serial unique not null primary key,
|
||||||
owner_id int references accounts (id) not null,
|
owner_id int references accounts (id) not null,
|
||||||
name text not null,
|
name text not null,
|
||||||
description text not null,
|
description text not null,
|
||||||
state "LocalServiceState" not null default 'Pending'
|
state "LocalServiceState" not null default 'Pending'
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE local_service_items (
|
CREATE TABLE local_service_items (
|
||||||
id serial unique not null primary key,
|
id serial unique not null primary key,
|
||||||
local_service_id int references local_services (id) not null,
|
local_service_id int references local_services (id) not null,
|
||||||
name text not null,
|
name text not null,
|
||||||
price bigint not null,
|
price bigint not null,
|
||||||
item_order int not null
|
item_order int not null
|
||||||
);
|
);
|
||||||
|
@ -1 +1,2 @@
|
|||||||
ALTER TABLE accounts ADD COLUMN email text not null default '' unique;
|
ALTER TABLE accounts
|
||||||
|
ADD COLUMN email text not null default '' unique;
|
||||||
|
@ -1 +1,2 @@
|
|||||||
ALTER TABLE accounts ADD COLUMN facebook_id TEXT DEFAULT NULL;
|
ALTER TABLE accounts
|
||||||
|
ADD COLUMN facebook_id TEXT DEFAULT NULL;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use crate::routes::render_index;
|
use crate::routes::render_index;
|
||||||
use actix_identity::{CookieIdentityPolicy, IdentityService};
|
use actix_identity::{CookieIdentityPolicy, IdentityService};
|
||||||
use actix_web::{web, web::Data, App, HttpResponse, HttpServer};
|
use actix_web::{web, web::Data, App, HttpServer};
|
||||||
|
|
||||||
mod auth;
|
mod auth;
|
||||||
mod model;
|
mod model;
|
||||||
|
@ -4,7 +4,7 @@ use sqlx::{FromRow, Type};
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(Debug, PartialOrd, PartialEq, Serialize, Deserialize, Type)]
|
#[derive(Debug, PartialOrd, PartialEq, Copy, Clone, Serialize, Deserialize, Type)]
|
||||||
pub enum AccountType {
|
pub enum AccountType {
|
||||||
User,
|
User,
|
||||||
Business,
|
Business,
|
||||||
@ -63,7 +63,7 @@ pub struct Token {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, FromRow)]
|
#[derive(Debug, Serialize, Deserialize, FromRow)]
|
||||||
pub struct LocalService {
|
pub struct LocalBusiness {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub owner_id: i32,
|
pub owner_id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -72,7 +72,7 @@ pub struct LocalService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, FromRow)]
|
#[derive(Debug, Serialize, Deserialize, FromRow)]
|
||||||
pub struct LocalServiceItem {
|
pub struct LocalBusinessItem {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub local_service_id: i32,
|
pub local_service_id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
@ -36,6 +36,12 @@ impl Page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct BusinessItemInput {
|
||||||
|
pub name: String,
|
||||||
|
pub price: u32,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct LocalService {
|
pub struct LocalService {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
@ -43,11 +49,11 @@ pub struct LocalService {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: String,
|
pub description: String,
|
||||||
pub state: db::LocalServiceState,
|
pub state: db::LocalServiceState,
|
||||||
pub items: Vec<db::LocalServiceItem>,
|
pub items: Vec<db::LocalBusinessItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v> From<(db::LocalService, &'v mut Vec<db::LocalServiceItem>)> for LocalService {
|
impl<'v> From<(db::LocalBusiness, &'v mut Vec<db::LocalBusinessItem>)> for LocalService {
|
||||||
fn from((service, items): (db::LocalService, &'v mut Vec<db::LocalServiceItem>)) -> Self {
|
fn from((service, items): (db::LocalBusiness, &'v mut Vec<db::LocalBusinessItem>)) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: service.id,
|
id: service.id,
|
||||||
owner_id: service.owner_id,
|
owner_id: service.owner_id,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::model::db;
|
use crate::model::db;
|
||||||
use crate::model::db::AccountType;
|
use crate::model::db::AccountType;
|
||||||
use crate::model::view::Page;
|
use crate::model::view::{self, Page};
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
use actix_files::Files;
|
use actix_files::Files;
|
||||||
use actix_identity::Identity;
|
use actix_identity::Identity;
|
||||||
@ -39,8 +39,8 @@ pub async fn index(db: Data<sqlx::PgPool>, id: Identity) -> HttpResponse {
|
|||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let (services, mut items) = {
|
let (services, mut items) = {
|
||||||
use crate::model::db::{LocalService, LocalServiceItem};
|
use crate::model::db::{LocalBusiness, LocalBusinessItem};
|
||||||
let services: Vec<LocalService> = sqlx::query_as(
|
let services: Vec<LocalBusiness> = sqlx::query_as(
|
||||||
r#"
|
r#"
|
||||||
SELECT id, owner_id, name, description, state
|
SELECT id, owner_id, name, description, state
|
||||||
FROM local_services
|
FROM local_services
|
||||||
@ -58,7 +58,7 @@ ORDER BY id
|
|||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let items: Vec<LocalServiceItem> = sqlx::query_as(
|
let items: Vec<LocalBusinessItem> = sqlx::query_as(
|
||||||
r#"
|
r#"
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
@ -132,6 +132,9 @@ struct RegisterForm {
|
|||||||
password: String,
|
password: String,
|
||||||
facebook_id: Option<String>,
|
facebook_id: Option<String>,
|
||||||
account_type: db::AccountType,
|
account_type: db::AccountType,
|
||||||
|
items: Option<Vec<view::BusinessItemInput>>,
|
||||||
|
name: Option<String>,
|
||||||
|
description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/register")]
|
#[post("/register")]
|
||||||
@ -143,13 +146,17 @@ async fn register(
|
|||||||
let form = form.into_inner();
|
let form = form.into_inner();
|
||||||
let pool = db.into_inner();
|
let pool = db.into_inner();
|
||||||
if form.account_type == AccountType::Admin {
|
if form.account_type == AccountType::Admin {
|
||||||
return HttpResponse::BadRequest().body("Breach attempt detected!");
|
return HttpResponse::BadRequest().body("Security breach attempt detected!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut t = pool.begin().await.unwrap();
|
||||||
|
|
||||||
let pass = match utils::encrypt(&form.password) {
|
let pass = match utils::encrypt(&form.password) {
|
||||||
Ok(pass) => pass,
|
Ok(pass) => pass,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("{:?}", e);
|
tracing::error!("{:?}", e);
|
||||||
|
dbg!(e);
|
||||||
|
t.rollback().await.unwrap();
|
||||||
return HttpResponse::BadRequest().body(
|
return HttpResponse::BadRequest().body(
|
||||||
AccountTemplate {
|
AccountTemplate {
|
||||||
account: None,
|
account: None,
|
||||||
@ -165,7 +172,7 @@ async fn register(
|
|||||||
let res: sqlx::Result<db::Account> = sqlx::query_as(
|
let res: sqlx::Result<db::Account> = sqlx::query_as(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO accounts (login, email, pass, facebook_id, account_type)
|
INSERT INTO accounts (login, email, pass, facebook_id, account_type)
|
||||||
VALUES ($1, $2, $3, $4)
|
VALUES ($1, $2, $3, $4, $5)
|
||||||
RETURNING id, login, email, pass, facebook_id, account_type
|
RETURNING id, login, email, pass, facebook_id, account_type
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
@ -173,24 +180,19 @@ RETURNING id, login, email, pass, facebook_id, account_type
|
|||||||
.bind(form.email)
|
.bind(form.email)
|
||||||
.bind(pass)
|
.bind(pass)
|
||||||
.bind(form.facebook_id)
|
.bind(form.facebook_id)
|
||||||
.fetch_one(&*pool)
|
.bind(form.account_type)
|
||||||
|
.fetch_one(&mut t)
|
||||||
.await;
|
.await;
|
||||||
match res {
|
let account = match res {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
id.remember(format!("{}", res.id));
|
id.remember(format!("{}", res.id));
|
||||||
HttpResponse::Ok().body(
|
res
|
||||||
AccountTemplate {
|
|
||||||
account: Some(res),
|
|
||||||
error: None,
|
|
||||||
page: Page::Register,
|
|
||||||
}
|
|
||||||
.render()
|
|
||||||
.unwrap(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
tracing::error!("{e}");
|
||||||
HttpResponse::BadRequest().body(
|
dbg!(e);
|
||||||
|
t.rollback().await.unwrap();
|
||||||
|
return HttpResponse::BadRequest().body(
|
||||||
AccountTemplate {
|
AccountTemplate {
|
||||||
account: None,
|
account: None,
|
||||||
error: Some("Problem z utworzeniem konta".into()),
|
error: Some("Problem z utworzeniem konta".into()),
|
||||||
@ -198,9 +200,92 @@ RETURNING id, login, email, pass, facebook_id, account_type
|
|||||||
}
|
}
|
||||||
.render()
|
.render()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if matches!(form.account_type, AccountType::Business) {
|
||||||
|
let name = form.name.as_deref().unwrap_or_default();
|
||||||
|
let owner_id = account.id;
|
||||||
|
let description = form.description.as_deref().unwrap_or_default();
|
||||||
|
|
||||||
|
let res: sqlx::Result<db::LocalBusiness> = sqlx::query_as(
|
||||||
|
r#"
|
||||||
|
INSERT INTO local_services (name, owner_id, description)
|
||||||
|
VALUES ($1, $2, $3)
|
||||||
|
RETURNING id, owner_id, name, description, state
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(name)
|
||||||
|
.bind(owner_id)
|
||||||
|
.bind(description)
|
||||||
|
.fetch_one(&mut t)
|
||||||
|
.await;
|
||||||
|
let business = match res {
|
||||||
|
Ok(business) => business,
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("{e}");
|
||||||
|
dbg!(e);
|
||||||
|
t.rollback().await.unwrap();
|
||||||
|
return HttpResponse::BadRequest().body(
|
||||||
|
AccountTemplate {
|
||||||
|
account: None,
|
||||||
|
error: Some("Problem z utworzeniem konta".into()),
|
||||||
|
page: Page::Register,
|
||||||
|
}
|
||||||
|
.render()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (idx, item) in form.items.as_deref().unwrap_or_default().iter().enumerate() {
|
||||||
|
let res: sqlx::Result<db::LocalBusinessItem> = sqlx::query_as(
|
||||||
|
r#"
|
||||||
|
INSERT INTO local_service_items (local_service_id, name, price, item_order)
|
||||||
|
VALUES ($1, $2, $3, $4)
|
||||||
|
RETURNING id, local_service_id, name, price, item_order
|
||||||
|
"#,
|
||||||
)
|
)
|
||||||
|
.bind(business.id)
|
||||||
|
.bind(&item.name)
|
||||||
|
.bind(item.price as i32)
|
||||||
|
.bind(idx as i32)
|
||||||
|
.fetch_one(&mut t)
|
||||||
|
.await;
|
||||||
|
match res {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!("{e}");
|
||||||
|
dbg!(e);
|
||||||
|
t.rollback().await.unwrap();
|
||||||
|
return HttpResponse::BadRequest().body(
|
||||||
|
AccountTemplate {
|
||||||
|
account: None,
|
||||||
|
error: Some("Problem z utworzeniem konta".into()),
|
||||||
|
page: Page::Register,
|
||||||
|
}
|
||||||
|
.render()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.commit().await.unwrap();
|
||||||
|
|
||||||
|
HttpResponse::SeeOther()
|
||||||
|
.append_header(("Location", "/"))
|
||||||
|
.body(
|
||||||
|
AccountTemplate {
|
||||||
|
account: Some(account),
|
||||||
|
error: None,
|
||||||
|
page: Page::Register,
|
||||||
|
}
|
||||||
|
.render()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/logout")]
|
#[post("/logout")]
|
||||||
|
Loading…
Reference in New Issue
Block a user