Add link as contact, ui fixes
This commit is contained in:
parent
6cff8e7a37
commit
bbf774d8d9
@ -160,6 +160,9 @@ customElements.define('contact-info-editor', class extends Component {
|
||||
if (s.match(/^[a-zA-Z\d.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z\d-]+(?:\.[a-zA-Z\d-]+)*$/)) {
|
||||
return 'email';
|
||||
}
|
||||
if (s.match(/https?:\/\//)) {
|
||||
return 'link';
|
||||
}
|
||||
return 'other';
|
||||
}
|
||||
});
|
||||
|
@ -23,7 +23,8 @@ customElements.define('contact-type-icon',
|
||||
:host([type="mobile"]) #mobile-icon {
|
||||
display: block;
|
||||
}
|
||||
path {
|
||||
:host([type='link']) #link-icon {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -45,6 +46,9 @@ customElements.define('contact-type-icon',
|
||||
<circle cx="272.723" cy="55.769" r="5.977"/>
|
||||
<circle cx="312.426" cy="55.769" r="5.977"/>
|
||||
</svg>
|
||||
<svg id="link-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 162.656 162.656" xml:space="preserve">
|
||||
<path d="M151.764 10.894c-14.522-14.522-38.152-14.525-52.676-.008l.003.003-22.979 22.983 10.607 10.605 22.983-22.988-.002-.002c8.678-8.663 22.785-8.658 31.457.014 8.673 8.672 8.672 22.786 0 31.461l-34.486 34.484a22.095 22.095 0 0 1-15.729 6.516 22.098 22.098 0 0 1-15.73-6.516L64.605 98.052c7.035 7.035 16.389 10.91 26.338 10.91 9.949 0 19.303-3.875 26.335-10.91l34.487-34.484c14.519-14.525 14.519-38.155-.001-52.674z"/><path d="M52.96 141.162c-8.675 8.67-22.788 8.668-31.461-.005-8.673-8.675-8.673-22.791-.001-31.465L55.98 75.21c8.675-8.674 22.789-8.674 31.462 0L98.05 64.604c-14.524-14.523-38.154-14.524-52.676 0L10.89 99.086c-14.519 14.523-14.519 38.154.001 52.678 7.263 7.262 16.801 10.893 26.341 10.892 9.536 0 19.074-3.629 26.333-10.887l.002-.001 22.984-22.99-10.608-10.606-22.983 22.99z"/>
|
||||
</svg>
|
||||
`);
|
||||
}
|
||||
|
||||
|
@ -8,8 +8,15 @@ customElements.define('local-business-item', class extends Component {
|
||||
constructor() {
|
||||
super(`
|
||||
<style>
|
||||
:host { display: block; }
|
||||
* { font-family: 'Cardo', sans-serif; }
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
* {
|
||||
font-family: 'Cardo', sans-serif;
|
||||
--img-width: 128px;
|
||||
--price-width: 160px;
|
||||
--name-width: calc(100% - var(--price-width) - var(--img-width) - 20px);
|
||||
}
|
||||
:host([picture-url = '']) #img {
|
||||
display: none;
|
||||
}
|
||||
@ -17,40 +24,47 @@ customElements.define('local-business-item', class extends Component {
|
||||
display: grid;
|
||||
grid-template-areas: 'img name' 'img price';
|
||||
}
|
||||
h3 {
|
||||
h3#name {
|
||||
font-weight: normal;
|
||||
grid-area: name;
|
||||
line-height: 1;
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 16px;
|
||||
width: var(--name-width);
|
||||
}
|
||||
#price {
|
||||
grid-area: price; text-align: right;
|
||||
grid-area: price;
|
||||
text-align: right;
|
||||
width: var(--price-width);
|
||||
}
|
||||
#img {
|
||||
width: 128px;
|
||||
max-width: 128px;
|
||||
width: var(--img-width);
|
||||
max-width: var(--img-width);
|
||||
grid-area: img;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
@media (min-width: 1000px) {
|
||||
#item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
h3 {
|
||||
h3#name {
|
||||
font-weight: normal;
|
||||
line-height: 1.6;
|
||||
width: calc(100% - 450px);
|
||||
width: var(--name-width);
|
||||
text-align: left;
|
||||
}
|
||||
#price {
|
||||
font-weight: bold;
|
||||
width: 180px;
|
||||
width: var(--price-width);
|
||||
}
|
||||
#img {
|
||||
width: 128px;
|
||||
width: var(--img-width);
|
||||
max-width: 128px;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,10 @@ customElements.define('local-business-list', class extends Component {
|
||||
::slotted(local-business) {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
#search {
|
||||
margin-bottom: 16px;;
|
||||
margin-top: 16px;;
|
||||
}
|
||||
@media only screen and (min-device-width: 1000px) {
|
||||
article {
|
||||
margin: 0;
|
||||
@ -51,7 +55,7 @@ customElements.define('local-business-list', class extends Component {
|
||||
}
|
||||
</style>
|
||||
<article>
|
||||
<section>
|
||||
<section id="search">
|
||||
<search-input target="local-business"></search-input>
|
||||
</section>
|
||||
<section id="items">
|
||||
|
@ -20,6 +20,9 @@ customElements.define('marketplace-offer', class extends Component {
|
||||
|
||||
section {
|
||||
margin-bottom: 16px;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
#preview {
|
||||
@ -37,8 +40,7 @@ customElements.define('marketplace-offer', class extends Component {
|
||||
}
|
||||
|
||||
:host([price-range-max="0"]) #sep, :host([price-range]) #sep,
|
||||
:host([price-range-max="0"]) #price-min, :host([price-range]) #price-min
|
||||
{
|
||||
:host([price-range-max="0"]) #price-min, :host([price-range]) #price-min {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@ -87,7 +89,7 @@ customElements.define('marketplace-offer', class extends Component {
|
||||
justify-content: end;
|
||||
}
|
||||
|
||||
@media only screen and (min-device-width: 1200px) {
|
||||
@media only screen and (min-device-width: 1000px) {
|
||||
#details {
|
||||
display: grid;
|
||||
column-gap: 16px;
|
||||
@ -125,24 +127,32 @@ customElements.define('marketplace-offer', class extends Component {
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
a {
|
||||
font-style: normal;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
${ INPUT_STYLE }
|
||||
</style>
|
||||
<section id="details">
|
||||
<div id="preview">
|
||||
<image-popup src="" id="picture">
|
||||
</image-popup>
|
||||
</div>
|
||||
<p id="description"></p>
|
||||
<span id="price-min"></span>
|
||||
<span id="sep">-</span>
|
||||
<span id="price-max"></span>
|
||||
</section>
|
||||
<section id="contacts">
|
||||
<span style="margin-right: 10px; font-weight: bold">Kontakt:</span>
|
||||
<slot name="contacts"></slot>
|
||||
</section>
|
||||
<article>
|
||||
<section id="details">
|
||||
<div id="preview">
|
||||
<image-popup src="" id="picture">
|
||||
</image-popup>
|
||||
</div>
|
||||
<p id="description"></p>
|
||||
<span id="price-min"></span>
|
||||
<span id="sep">-</span>
|
||||
<span id="price-max"></span>
|
||||
</section>
|
||||
<section id="contacts">
|
||||
<span style="margin-right: 10px; font-weight: bold">Kontakt:</span>
|
||||
<slot name="contacts"></slot>
|
||||
</section>
|
||||
</article>
|
||||
`);
|
||||
this.#price_range = new PriceRange(0, 0);
|
||||
}
|
||||
|
@ -26,12 +26,19 @@ customElements.define('marketplace-offers', class extends Component {
|
||||
:host([account-id]) #publishSection {
|
||||
display: block;
|
||||
}
|
||||
::slotted(marketplace-offer), ::slotted(user-edit-offer) {
|
||||
::slotted(a), ::slotted(marketplace-offer), ::slotted(user-edit-offer) {
|
||||
margin-bottom: 20px;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
font-style: normal;
|
||||
}
|
||||
::slotted([search-visible='invisible']) {
|
||||
display: none;
|
||||
}
|
||||
#search {
|
||||
margin-bottom: 16px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
@media only screen and (min-device-width: 1000px) {
|
||||
#offers {
|
||||
display: flex;
|
||||
@ -39,9 +46,12 @@ customElements.define('marketplace-offers', class extends Component {
|
||||
flex-wrap: wrap;
|
||||
justify-items: stretch;
|
||||
}
|
||||
::slotted(marketplace-offer), ::slotted(user-edit-offer) {
|
||||
::slotted(a), ::slotted(marketplace-offer), ::slotted(user-edit-offer) {
|
||||
width: calc(33% - 40px);
|
||||
margin: 0 20px 20px;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
${ BUTTON_STYLE }
|
||||
@ -51,7 +61,7 @@ customElements.define('marketplace-offers', class extends Component {
|
||||
<button id="publish" class="btn">Dodaj ogłoszenie</button>
|
||||
</section>
|
||||
<section><slot></slot></section>
|
||||
<section>
|
||||
<section id="search">
|
||||
<search-input target="user-edit-offer, marketplace-offer"></search-input>
|
||||
</section>
|
||||
<section id="offers">
|
||||
|
@ -15,6 +15,11 @@ customElements.define('user-edit-offer', class extends Component {
|
||||
:host([mode='view']) #view { display: block; }
|
||||
:host([mode='form']) #form { display: block; }
|
||||
:host([state='Finished']) #finishForm { display: none; }
|
||||
section, a, ::slotted(a) {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
font-style: normal;
|
||||
}
|
||||
#actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -25,8 +25,25 @@ customElements.define('search-input', class extends Component {
|
||||
border-bottom: 1px solid #ccc;
|
||||
text-indent: 20px;
|
||||
}
|
||||
svg { height: 24px; }
|
||||
section {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
<section>
|
||||
<svg
|
||||
viewBox="0 0 310.42 310.42"
|
||||
xml:space="preserve"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M273.587 214.965c49.11-49.111 49.11-129.021 0-178.132s-129.021-49.111-178.131 0C53.792 78.497 47.482 140.462 76.509 188.85c0 0 2.085 3.496-.731 6.312l-64.263 64.263c-12.791 12.79-15.837 30.675-4.493 42.02l1.953 1.951c11.343 11.345 29.229 8.301 42.019-4.49l64.128-64.128c2.951-2.951 6.448-.866 6.448-.866 48.387 29.026 110.353 22.717 152.017-18.947zM118.71 191.71c-36.288-36.288-36.287-95.332 0-131.62 36.288-36.287 95.333-36.288 131.62 0 36.288 36.287 36.288 95.332 0 131.62-36.287 36.287-95.331 36.287-131.62 0z"
|
||||
/>
|
||||
</svg>
|
||||
<input type="text" id="filter" placeholder="Znajdź (wyrażenia regularne są wspierane)" />
|
||||
</section>
|
||||
`);
|
||||
@ -52,10 +69,8 @@ customElements.define('search-input', class extends Component {
|
||||
super.connectedCallback();
|
||||
let node = this;
|
||||
while (node) {
|
||||
console.warn(node)
|
||||
if (node == null) return console.warn('no parent node', node);
|
||||
if (node instanceof ShadowRoot) {
|
||||
console.warn('node is shadow')
|
||||
this.#host = node.host;
|
||||
break;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
mode="icon"
|
||||
contact-id="{{contact.id}}"
|
||||
content="{{h.render_contact(contact.contact_type.as_str(), contact.content.as_str())}}"
|
||||
contact-type="{{contact.contact_type}}"
|
||||
type="{{contact.contact_type}}"
|
||||
></contact-info>
|
||||
{% endfor %}
|
||||
</contact-info-list>
|
||||
|
@ -25,7 +25,7 @@
|
||||
mode="icon"
|
||||
contact-id="{{contact.id}}"
|
||||
content="{{h.render_contact(contact.contact_type.as_str(), contact.content.as_str())}}"
|
||||
contact-type="{{contact.contact_type}}"
|
||||
type="{{contact.contact_type}}"
|
||||
></contact-info>
|
||||
{% endfor %}
|
||||
</contact-info-list>
|
||||
|
@ -22,17 +22,50 @@
|
||||
price-range-max="{{max}}"
|
||||
{% endmatch %}
|
||||
>
|
||||
<a href="/marketplace/{{offer.id}}">
|
||||
<marketplace-offer
|
||||
offer-id="{{offer.id}}"
|
||||
description="{{offer.description}}"
|
||||
picture-url="{{offer.picture_url}}"
|
||||
{% match offer.price_range %}
|
||||
{% when PriceRange::Free %}
|
||||
price-range-min="0"
|
||||
price-range-max="0"
|
||||
{% when PriceRange::Fixed with { value } %}
|
||||
price-range-min="{{value}}"
|
||||
price-range-max="0"
|
||||
{% when PriceRange::Range with { min, max } %}
|
||||
price-range-min="{{min}}"
|
||||
price-range-max="{{max}}"
|
||||
{% endmatch %}
|
||||
>
|
||||
<contact-info-list slot="contacts">
|
||||
{% for contact in offer.contacts %}
|
||||
<contact-info
|
||||
mode="icon"
|
||||
contact-id="{{contact.id}}"
|
||||
type="{{contact.contact_type}}"
|
||||
content="{{h.render_contact(contact.contact_type.as_str(), contact.content.as_str())}}"
|
||||
></contact-info>
|
||||
{% endfor %}
|
||||
</contact-info-list>
|
||||
</marketplace-offer>
|
||||
</a>
|
||||
</user-edit-offer>
|
||||
{% endfor %}
|
||||
|
||||
{% for offer in offers %}
|
||||
<a href="/marketplace/{{offer.id}}" slot="offer">
|
||||
<marketplace-offer
|
||||
|
||||
offer-id="{{offer.id}}"
|
||||
description="{{offer.description}}"
|
||||
picture-url="{{offer.picture_url}}"
|
||||
{% match offer.price_range %}
|
||||
{% when PriceRange::Free %}
|
||||
price-range-min="0"
|
||||
price-range-max="0"
|
||||
price-range="free"
|
||||
{% when PriceRange::Fixed with { value } %}
|
||||
price-range-min="{{value}}"
|
||||
price-range-max="0"
|
||||
price-range="{{value}}"
|
||||
{% when PriceRange::Range with { min, max } %}
|
||||
price-range-min="{{min}}"
|
||||
price-range-max="{{max}}"
|
||||
@ -49,36 +82,7 @@
|
||||
{% endfor %}
|
||||
</contact-info-list>
|
||||
</marketplace-offer>
|
||||
</user-edit-offer>
|
||||
{% endfor %}
|
||||
|
||||
{% for offer in offers %}
|
||||
<marketplace-offer
|
||||
slot="offer"
|
||||
offer-id="{{offer.id}}"
|
||||
description="{{offer.description}}"
|
||||
picture-url="{{offer.picture_url}}"
|
||||
{% match offer.price_range %}
|
||||
{% when PriceRange::Free %}
|
||||
price-range="free"
|
||||
{% when PriceRange::Fixed with { value } %}
|
||||
price-range="{{value}}"
|
||||
{% when PriceRange::Range with { min, max } %}
|
||||
price-range-min="{{min}}"
|
||||
price-range-max="{{max}}"
|
||||
{% endmatch %}
|
||||
>
|
||||
<contact-info-list slot="contacts">
|
||||
{% for contact in offer.contacts %}
|
||||
<contact-info
|
||||
mode="icon"
|
||||
contact-id="{{contact.id}}"
|
||||
type="{{contact.contact_type}}"
|
||||
content="{{h.render_contact(contact.contact_type.as_str(), contact.content.as_str())}}"
|
||||
></contact-info>
|
||||
{% endfor %}
|
||||
</contact-info-list>
|
||||
</marketplace-offer>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</marketplace-offers>
|
||||
{% endblock %}
|
||||
|
31
server/assets/templates/marketplace/show.html
Normal file
31
server/assets/templates/marketplace/show.html
Normal file
@ -0,0 +1,31 @@
|
||||
{% extends "../base.html" %}
|
||||
{% block content %}
|
||||
<marketplace-offer
|
||||
{{h.account_id_tag(account)}}
|
||||
offer-id="{{offer.id}}"
|
||||
description="{{offer.description}}"
|
||||
picture-url="{{offer.picture_url}}"
|
||||
{% match offer.price_range %}
|
||||
{% when PriceRange::Free %}
|
||||
price-range-min="0"
|
||||
price-range-max="0"
|
||||
{% when PriceRange::Fixed with { value } %}
|
||||
price-range-min="{{value}}"
|
||||
price-range-max="0"
|
||||
{% when PriceRange::Range with { min, max } %}
|
||||
price-range-min="{{min}}"
|
||||
price-range-max="{{max}}"
|
||||
{% endmatch %}
|
||||
>
|
||||
<contact-info-list slot="contacts">
|
||||
{% for contact in offer.contacts %}
|
||||
<contact-info
|
||||
mode="icon"
|
||||
contact-id="{{contact.id}}"
|
||||
type="{{contact.contact_type}}"
|
||||
content="{{h.render_contact(contact.contact_type.as_str(), contact.content.as_str())}}"
|
||||
></contact-info>
|
||||
{% endfor %}
|
||||
</contact-info-list>
|
||||
</marketplace-offer>
|
||||
{% endblock %}
|
@ -14,6 +14,7 @@ SELECT
|
||||
content
|
||||
FROM
|
||||
contacts
|
||||
ORDER BY contact_type, id ASC
|
||||
"#,
|
||||
)
|
||||
.fetch_all(t)
|
||||
|
@ -57,9 +57,14 @@ ORDER BY id DESC
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub async fn offer_by_id(t: &mut T<'_>, account_id: i32, offer_id: i32) -> Result<db::Offer> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
pub async fn offer_by_id(
|
||||
t: &mut T<'_>,
|
||||
account_id: Option<i32>,
|
||||
offer_id: i32,
|
||||
) -> Result<db::Offer> {
|
||||
match account_id {
|
||||
Some(account_id) => sqlx::query_as(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
owner_id,
|
||||
@ -72,9 +77,26 @@ FROM offers
|
||||
WHERE owner_id = $1 AND id = $2
|
||||
LIMIT 1
|
||||
"#,
|
||||
)
|
||||
.bind(account_id)
|
||||
.bind(offer_id)
|
||||
)
|
||||
.bind(account_id)
|
||||
.bind(offer_id),
|
||||
None => sqlx::query_as(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
owner_id,
|
||||
price_range,
|
||||
description,
|
||||
picture_url,
|
||||
state,
|
||||
created_at
|
||||
FROM offers
|
||||
WHERE id = $1
|
||||
LIMIT 1
|
||||
"#,
|
||||
)
|
||||
.bind(offer_id),
|
||||
}
|
||||
.fetch_one(t)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
|
@ -314,9 +314,15 @@ impl Responder for HttpResult {
|
||||
let status_code = self.status_code();
|
||||
match self {
|
||||
HttpResult::Json { body, code } => HttpResponse::build(code)
|
||||
.append_header(("Sec-GPC-field-name", "Sec-GPC"))
|
||||
.append_header(("Sec-GPC-field-value", "1"))
|
||||
.append_header(("Sec-GPC", "1"))
|
||||
.content_type("application/json")
|
||||
.body(body),
|
||||
HttpResult::Html { body, code } => HttpResponse::build(code)
|
||||
.append_header(("Sec-GPC-field-name", "Sec-GPC"))
|
||||
.append_header(("Sec-GPC-field-value", "1"))
|
||||
.append_header(("Sec-GPC", "1"))
|
||||
.content_type("text/html")
|
||||
.body(body),
|
||||
HttpResult::Err {
|
||||
|
@ -37,6 +37,13 @@ pub async fn render_index() -> HttpResponse {
|
||||
)
|
||||
}
|
||||
|
||||
#[get("/.well-known/gpc.json")]
|
||||
async fn gpc() -> HttpResponse {
|
||||
HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body("{\"gpc\":true,\"lastUpdate\":\"1997-03-10\"}")
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
async fn index(req: HttpRequest) -> HttpResult {
|
||||
HttpResult::goto(&req, "/marketplace")
|
||||
@ -62,5 +69,6 @@ pub fn configure(config: &mut ServiceConfig) {
|
||||
.prefer_utf8(true)
|
||||
.show_files_listing(),
|
||||
)
|
||||
.service(index);
|
||||
.service(index)
|
||||
.service(gpc);
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ async fn edit_marketplace(
|
||||
}
|
||||
};
|
||||
|
||||
let offer = match queries::offer_by_id(&mut t, account.id, offer_id).await {
|
||||
let offer = match queries::offer_by_id(&mut t, Some(account.id), offer_id).await {
|
||||
Ok(offer) => offer,
|
||||
Err(e) => {
|
||||
dbg!(e);
|
||||
@ -146,7 +146,7 @@ async fn edit_marketplace(
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Template)]
|
||||
#[template(path = "./marketplace/edit.html")]
|
||||
#[template(path = "./marketplace/show.html")]
|
||||
struct ShowOfferTemplate {
|
||||
account: Option<db::Account>,
|
||||
error: Option<String>,
|
||||
@ -176,7 +176,7 @@ async fn show_marketplace(
|
||||
return HttpResult::res(
|
||||
&req,
|
||||
StatusCode::NOT_FOUND,
|
||||
EditOfferTemplate {
|
||||
ShowOfferTemplate {
|
||||
page: Page::Marketplace,
|
||||
account,
|
||||
error: Some("Oferta nie istnieje".into()),
|
||||
@ -186,14 +186,14 @@ async fn show_marketplace(
|
||||
}
|
||||
};
|
||||
|
||||
let offer = match queries::offer_by_id(&mut t, account.id, offer_id).await {
|
||||
let offer = match queries::offer_by_id(&mut t, None, offer_id).await {
|
||||
Ok(offer) => offer,
|
||||
Err(e) => {
|
||||
dbg!(e);
|
||||
return HttpResult::res(
|
||||
&req,
|
||||
StatusCode::NOT_FOUND,
|
||||
EditOfferTemplate {
|
||||
ShowOfferTemplate {
|
||||
page: Page::Marketplace,
|
||||
account: Some(account),
|
||||
error: Some("Oferta nie istnieje".into()),
|
||||
@ -208,7 +208,7 @@ async fn show_marketplace(
|
||||
HttpResult::res(
|
||||
&req,
|
||||
StatusCode::OK,
|
||||
EditOfferTemplate {
|
||||
ShowOfferTemplate {
|
||||
page: Page::Marketplace,
|
||||
account: Some(account),
|
||||
offer: view::Offer::from((offer, &vec![])),
|
||||
|
Loading…
Reference in New Issue
Block a user