add: ability to create seller account
This commit is contained in:
parent
e4468e4768
commit
aea764948c
13 changed files with 356 additions and 0 deletions
|
@ -58,6 +58,7 @@ pub const AUTH_BASE: &str = include_str!("./public/html/auth/base.lisp");
|
||||||
pub const AUTH_LOGIN: &str = include_str!("./public/html/auth/login.lisp");
|
pub const AUTH_LOGIN: &str = include_str!("./public/html/auth/login.lisp");
|
||||||
pub const AUTH_REGISTER: &str = include_str!("./public/html/auth/register.lisp");
|
pub const AUTH_REGISTER: &str = include_str!("./public/html/auth/register.lisp");
|
||||||
pub const AUTH_CONNECTION: &str = include_str!("./public/html/auth/connection.lisp");
|
pub const AUTH_CONNECTION: &str = include_str!("./public/html/auth/connection.lisp");
|
||||||
|
pub const AUTH_SELLER_CONNECTION: &str = include_str!("./public/html/auth/seller_connection.lisp");
|
||||||
|
|
||||||
pub const PROFILE_BASE: &str = include_str!("./public/html/profile/base.lisp");
|
pub const PROFILE_BASE: &str = include_str!("./public/html/profile/base.lisp");
|
||||||
pub const PROFILE_POSTS: &str = include_str!("./public/html/profile/posts.lisp");
|
pub const PROFILE_POSTS: &str = include_str!("./public/html/profile/posts.lisp");
|
||||||
|
@ -139,6 +140,8 @@ pub const LITTLEWEB_SERVICE: &str = include_str!("./public/html/littleweb/servic
|
||||||
pub const LITTLEWEB_DOMAIN: &str = include_str!("./public/html/littleweb/domain.lisp");
|
pub const LITTLEWEB_DOMAIN: &str = include_str!("./public/html/littleweb/domain.lisp");
|
||||||
pub const LITTLEWEB_BROWSER: &str = include_str!("./public/html/littleweb/browser.lisp");
|
pub const LITTLEWEB_BROWSER: &str = include_str!("./public/html/littleweb/browser.lisp");
|
||||||
|
|
||||||
|
pub const MARKETPLACE_SELLER: &str = include_str!("./public/html/marketplace/seller.lisp");
|
||||||
|
|
||||||
// langs
|
// langs
|
||||||
pub const LANG_EN_US: &str = include_str!("./langs/en-US.toml");
|
pub const LANG_EN_US: &str = include_str!("./langs/en-US.toml");
|
||||||
|
|
||||||
|
@ -146,6 +149,7 @@ pub const LANG_EN_US: &str = include_str!("./langs/en-US.toml");
|
||||||
|
|
||||||
pub const VENDOR_SPOTIFY_ICON: &str = include_str!("./public/images/vendor/spotify.svg");
|
pub const VENDOR_SPOTIFY_ICON: &str = include_str!("./public/images/vendor/spotify.svg");
|
||||||
pub const VENDOR_LAST_FM_ICON: &str = include_str!("./public/images/vendor/last-fm.svg");
|
pub const VENDOR_LAST_FM_ICON: &str = include_str!("./public/images/vendor/last-fm.svg");
|
||||||
|
pub const VENDOR_STRIPE_ICON: &str = include_str!("./public/images/vendor/stripe.svg");
|
||||||
|
|
||||||
pub const TETRATTO_BUNNY: &[u8] = include_bytes!("./public/images/tetratto_bunny.webp");
|
pub const TETRATTO_BUNNY: &[u8] = include_bytes!("./public/images/tetratto_bunny.webp");
|
||||||
|
|
||||||
|
@ -343,6 +347,7 @@ pub(crate) fn lisp_plugins() -> HashMap<String, Box<dyn FnMut(Element) -> Elemen
|
||||||
pub(crate) async fn write_assets(config: &Config) -> PathBufD {
|
pub(crate) async fn write_assets(config: &Config) -> PathBufD {
|
||||||
vendor_icon!("spotify", VENDOR_SPOTIFY_ICON, config.dirs.icons);
|
vendor_icon!("spotify", VENDOR_SPOTIFY_ICON, config.dirs.icons);
|
||||||
vendor_icon!("last_fm", VENDOR_LAST_FM_ICON, config.dirs.icons);
|
vendor_icon!("last_fm", VENDOR_LAST_FM_ICON, config.dirs.icons);
|
||||||
|
vendor_icon!("stripe", VENDOR_STRIPE_ICON, config.dirs.icons);
|
||||||
bin_icon!("tetratto_bunny.webp", TETRATTO_BUNNY, config.dirs.assets);
|
bin_icon!("tetratto_bunny.webp", TETRATTO_BUNNY, config.dirs.assets);
|
||||||
|
|
||||||
// ...
|
// ...
|
||||||
|
@ -364,6 +369,7 @@ pub(crate) async fn write_assets(config: &Config) -> PathBufD {
|
||||||
write_template!(html_path->"auth/login.html"(crate::assets::AUTH_LOGIN) --config=config --lisp plugins);
|
write_template!(html_path->"auth/login.html"(crate::assets::AUTH_LOGIN) --config=config --lisp plugins);
|
||||||
write_template!(html_path->"auth/register.html"(crate::assets::AUTH_REGISTER) --config=config --lisp plugins);
|
write_template!(html_path->"auth/register.html"(crate::assets::AUTH_REGISTER) --config=config --lisp plugins);
|
||||||
write_template!(html_path->"auth/connection.html"(crate::assets::AUTH_CONNECTION) --config=config --lisp plugins);
|
write_template!(html_path->"auth/connection.html"(crate::assets::AUTH_CONNECTION) --config=config --lisp plugins);
|
||||||
|
write_template!(html_path->"auth/seller_connection.html"(crate::assets::AUTH_SELLER_CONNECTION) --config=config --lisp plugins);
|
||||||
|
|
||||||
write_template!(html_path->"profile/base.html"(crate::assets::PROFILE_BASE) -d "profile" --config=config --lisp plugins);
|
write_template!(html_path->"profile/base.html"(crate::assets::PROFILE_BASE) -d "profile" --config=config --lisp plugins);
|
||||||
write_template!(html_path->"profile/posts.html"(crate::assets::PROFILE_POSTS) --config=config --lisp plugins);
|
write_template!(html_path->"profile/posts.html"(crate::assets::PROFILE_POSTS) --config=config --lisp plugins);
|
||||||
|
@ -440,6 +446,8 @@ pub(crate) async fn write_assets(config: &Config) -> PathBufD {
|
||||||
write_template!(html_path->"littleweb/domain.html"(crate::assets::LITTLEWEB_DOMAIN) --config=config --lisp plugins);
|
write_template!(html_path->"littleweb/domain.html"(crate::assets::LITTLEWEB_DOMAIN) --config=config --lisp plugins);
|
||||||
write_template!(html_path->"littleweb/browser.html"(crate::assets::LITTLEWEB_BROWSER) --config=config --lisp plugins);
|
write_template!(html_path->"littleweb/browser.html"(crate::assets::LITTLEWEB_BROWSER) --config=config --lisp plugins);
|
||||||
|
|
||||||
|
write_template!(html_path->"marketplace/seller.html"(crate::assets::MARKETPLACE_SELLER) -d "marketplace" --config=config --lisp plugins);
|
||||||
|
|
||||||
html_path
|
html_path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -285,3 +285,9 @@ version = "1.0.0"
|
||||||
"littleweb:action.edit_site_name" = "Edit site name"
|
"littleweb:action.edit_site_name" = "Edit site name"
|
||||||
"littleweb:action.rename" = "Rename"
|
"littleweb:action.rename" = "Rename"
|
||||||
"littleweb:action.add" = "Add"
|
"littleweb:action.add" = "Add"
|
||||||
|
|
||||||
|
"marketplace:label.products" = "Products"
|
||||||
|
"marketplace:label.status" = "Status"
|
||||||
|
"marketplace:action.get_started" = "Get started"
|
||||||
|
"marketplace:action.finsh_setting_up_account" = "Finish setting up my account"
|
||||||
|
"marketplace:action.open_seller_dashboard" = "Open seller dashboard"
|
||||||
|
|
|
@ -583,6 +583,9 @@ input[type="checkbox"]:checked {
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
height: max-content;
|
height: max-content;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification.tr {
|
.notification.tr {
|
||||||
|
@ -597,6 +600,11 @@ input[type="checkbox"]:checked {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notification .icon {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
/* chip */
|
/* chip */
|
||||||
.chip {
|
.chip {
|
||||||
background: var(--color-primary);
|
background: var(--color-primary);
|
||||||
|
|
25
crates/app/src/public/html/auth/seller_connection.lisp
Normal file
25
crates/app/src/public/html/auth/seller_connection.lisp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
(text "{% extends \"auth/base.html\" %} {% block head %}")
|
||||||
|
(title
|
||||||
|
(text "Connection"))
|
||||||
|
|
||||||
|
(text "{% endblock %} {% block title %}Connection{% endblock %} {% block content %}")
|
||||||
|
(div
|
||||||
|
("class" "w-full flex-col gap-2")
|
||||||
|
("id" "status")
|
||||||
|
(b
|
||||||
|
(text "Working...")))
|
||||||
|
|
||||||
|
(text "{% if connection_type == \"refresh\" %}")
|
||||||
|
(script
|
||||||
|
("defer" "true")
|
||||||
|
(text "setTimeout(async () => {
|
||||||
|
trigger(\"seller::onboarding\");
|
||||||
|
}, 1000);"))
|
||||||
|
(text "{% elif connection_type == \"return\" %}")
|
||||||
|
(script
|
||||||
|
("defer" "true")
|
||||||
|
(text "setTimeout(async () => {
|
||||||
|
document.getElementById(\"status\").innerHTML =
|
||||||
|
`<b>Account updated.</b> You can now close this tab.`;
|
||||||
|
}, 1000);"))
|
||||||
|
(text "{%- endif %} {% endblock %}")
|
|
@ -331,3 +331,17 @@
|
||||||
(span
|
(span
|
||||||
(text "{{ text \"settings:tab.connections\" }}")))
|
(text "{{ text \"settings:tab.connections\" }}")))
|
||||||
(text "{%- endmacro %}")
|
(text "{%- endmacro %}")
|
||||||
|
|
||||||
|
(text "{% macro seller_settings_nav_options() -%}")
|
||||||
|
(a
|
||||||
|
("data-tab-button" "account")
|
||||||
|
("class" "active")
|
||||||
|
("href" "#/account")
|
||||||
|
(icon (text "smile"))
|
||||||
|
(span (str (text "settings:tab.account"))))
|
||||||
|
(a
|
||||||
|
("data-tab-button" "products")
|
||||||
|
("href" "#/products")
|
||||||
|
(icon (text "package"))
|
||||||
|
(span (str (text "marketplace:label.products"))))
|
||||||
|
(text "{%- endmacro %}")
|
||||||
|
|
79
crates/app/src/public/html/marketplace/seller.lisp
Normal file
79
crates/app/src/public/html/marketplace/seller.lisp
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
(text "{% extends \"root.html\" %} {% block head %}")
|
||||||
|
(title
|
||||||
|
(text "Seller settings - {{ config.name }}"))
|
||||||
|
(text "{% endblock %} {% block body %} {{ macros::nav() }}")
|
||||||
|
(main
|
||||||
|
("class" "flex flex-col gap-2")
|
||||||
|
|
||||||
|
; nav
|
||||||
|
(div
|
||||||
|
("class" "mobile_nav mobile")
|
||||||
|
; primary nav
|
||||||
|
(div
|
||||||
|
("class" "dropdown")
|
||||||
|
("style" "width: max-content")
|
||||||
|
(button
|
||||||
|
("class" "raised small")
|
||||||
|
("onclick" "trigger('atto::hooks::dropdown', [event])")
|
||||||
|
("exclude" "dropdown")
|
||||||
|
(icon (text "sliders-horizontal"))
|
||||||
|
(span ("class" "current_tab_text") (text "account")))
|
||||||
|
(div
|
||||||
|
("class" "inner left")
|
||||||
|
(text "{{ macros::seller_settings_nav_options() }}"))))
|
||||||
|
|
||||||
|
; nav desktop
|
||||||
|
(div
|
||||||
|
("class" "desktop pillmenu")
|
||||||
|
(text "{{ macros::seller_settings_nav_options() }}"))
|
||||||
|
|
||||||
|
; ...
|
||||||
|
(div
|
||||||
|
("class" "card w-full lowered flex flex-col gap-2")
|
||||||
|
("data-tab" "account")
|
||||||
|
(div
|
||||||
|
("class" "card-nest w-full")
|
||||||
|
(div
|
||||||
|
("class" "card small flex items-center gap-2")
|
||||||
|
(div
|
||||||
|
("class" "notification")
|
||||||
|
("style" "width: 46px")
|
||||||
|
(icon (text "stripe")))
|
||||||
|
|
||||||
|
(b (str (text "marketplace:label.status"))))
|
||||||
|
|
||||||
|
(div
|
||||||
|
("class" "card")
|
||||||
|
(text "{% if user.seller_data.account_id -%}")
|
||||||
|
(text "{% if user.seller_data.completed_onboarding -%}")
|
||||||
|
; completed onboarding + has stripe account linked
|
||||||
|
(button
|
||||||
|
("onclick" "trigger('seller::login')")
|
||||||
|
(icon (text "arrow-right"))
|
||||||
|
(str (text "marketplace:action.open_seller_dashboard")))
|
||||||
|
(text "{% else %}")
|
||||||
|
; not completed onboarding
|
||||||
|
(p (text "You've not finished setting up your Stripe account."))
|
||||||
|
(p (text "Please complete onboarding to accept payments."))
|
||||||
|
|
||||||
|
(button
|
||||||
|
("onclick" "trigger('seller::onboarding')")
|
||||||
|
(icon (text "arrow-right"))
|
||||||
|
(str (text "marketplace:action.finsh_setting_up_account")))
|
||||||
|
(text "{%- endif %}")
|
||||||
|
(text "{% else %}")
|
||||||
|
; doesn't have a stripe account linked
|
||||||
|
(button
|
||||||
|
("onclick" "trigger('seller::register')")
|
||||||
|
(icon (text "arrow-right"))
|
||||||
|
(str (text "marketplace:action.get_started")))
|
||||||
|
(text "{%- endif %}"))))
|
||||||
|
|
||||||
|
(div
|
||||||
|
("class" "card w-full lowered hidden flex flex-col gap-2")
|
||||||
|
("data-tab" "products")
|
||||||
|
(div
|
||||||
|
("class" "card w-full flex flex-wrap gap-2")
|
||||||
|
)))
|
||||||
|
|
||||||
|
(text "{% endblock %}")
|
1
crates/app/src/public/images/vendor/stripe.svg
vendored
Normal file
1
crates/app/src/public/images/vendor/stripe.svg
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" x="0" y="0" viewBox="0 0 468 222.5" style="enable-background:new 0 0 468 222.5" xml:space="preserve"><style>.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#635bff}</style><path class="st0" d="M414 113.4c0-25.6-12.4-45.8-36.1-45.8-23.8 0-38.2 20.2-38.2 45.6 0 30.1 17 45.3 41.4 45.3 11.9 0 20.9-2.7 27.7-6.5v-20c-6.8 3.4-14.6 5.5-24.5 5.5-9.7 0-18.3-3.4-19.4-15.2h48.9c0-1.3.2-6.5.2-8.9zm-49.4-9.5c0-11.3 6.9-16 13.2-16 6.1 0 12.6 4.7 12.6 16h-25.8zM301.1 67.6c-9.8 0-16.1 4.6-19.6 7.8l-1.3-6.2h-22v116.6l25-5.3.1-28.3c3.6 2.6 8.9 6.3 17.7 6.3 17.9 0 34.2-14.4 34.2-46.1-.1-29-16.6-44.8-34.1-44.8zm-6 68.9c-5.9 0-9.4-2.1-11.8-4.7l-.1-37.1c2.6-2.9 6.2-4.9 11.9-4.9 9.1 0 15.4 10.2 15.4 23.3 0 13.4-6.2 23.4-15.4 23.4zM223.8 61.7l25.1-5.4V36l-25.1 5.3zM223.8 69.3h25.1v87.5h-25.1zM196.9 76.7l-1.6-7.4h-21.6v87.5h25V97.5c5.9-7.7 15.9-6.3 19-5.2v-23c-3.2-1.2-14.9-3.4-20.8 7.4zM146.9 47.6l-24.4 5.2-.1 80.1c0 14.8 11.1 25.7 25.9 25.7 8.2 0 14.2-1.5 17.5-3.3V135c-3.2 1.3-19 5.9-19-8.9V90.6h19V69.3h-19l.1-21.7zM79.3 94.7c0-3.9 3.2-5.4 8.5-5.4 7.6 0 17.2 2.3 24.8 6.4V72.2c-8.3-3.3-16.5-4.6-24.8-4.6C67.5 67.6 54 78.2 54 95.9c0 27.6 38 23.2 38 35.1 0 4.6-4 6.1-9.6 6.1-8.3 0-18.9-3.4-27.3-8v23.8c9.3 4 18.7 5.7 27.3 5.7 20.8 0 35.1-10.3 35.1-28.2-.1-29.8-38.2-24.5-38.2-35.7z"/></svg>
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -1201,3 +1201,60 @@
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
const self = reg_ns("seller");
|
||||||
|
|
||||||
|
self.define("register", async () => {
|
||||||
|
await trigger("atto::debounce", ["seller::register"]);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!(await trigger("atto::confirm", [
|
||||||
|
"Are you sure you want to do this?",
|
||||||
|
]))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await (
|
||||||
|
await fetch("/api/v1/service_hooks/stripe/seller/register", {
|
||||||
|
method: "POST",
|
||||||
|
})
|
||||||
|
).json();
|
||||||
|
|
||||||
|
trigger("atto::toast", [res.ok ? "success" : "error", res.message]);
|
||||||
|
self.onboarding();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.define("onboarding", async () => {
|
||||||
|
await trigger("atto::debounce", ["seller::onboarding"]);
|
||||||
|
|
||||||
|
const res = await (
|
||||||
|
await fetch("/api/v1/service_hooks/stripe/seller/onboarding", {
|
||||||
|
method: "POST",
|
||||||
|
})
|
||||||
|
).json();
|
||||||
|
|
||||||
|
trigger("atto::toast", [res.ok ? "success" : "error", res.message]);
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
window.location.href = res.payload;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.define("login", async () => {
|
||||||
|
await trigger("atto::debounce", ["seller::login"]);
|
||||||
|
|
||||||
|
const res = await (
|
||||||
|
await fetch("/api/v1/service_hooks/stripe/seller/login", {
|
||||||
|
method: "POST",
|
||||||
|
})
|
||||||
|
).json();
|
||||||
|
|
||||||
|
trigger("atto::toast", [res.ok ? "success" : "error", res.message]);
|
||||||
|
|
||||||
|
if (res.ok) {
|
||||||
|
window.location.href = res.payload;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
|
@ -332,6 +332,10 @@ pub async fn onboarding_account_link_request(
|
||||||
None => return Json(Error::NotAllowed.into()),
|
None => return Json(Error::NotAllowed.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if user.seller_data.account_id.is_some() {
|
||||||
|
return Json(Error::NotAllowed.into());
|
||||||
|
}
|
||||||
|
|
||||||
let client = match data.3 {
|
let client = match data.3 {
|
||||||
Some(ref c) => c,
|
Some(ref c) => c,
|
||||||
None => return Json(Error::Unknown.into()),
|
None => return Json(Error::Unknown.into()),
|
||||||
|
@ -379,6 +383,10 @@ pub async fn create_seller_account_request(
|
||||||
None => return Json(Error::NotAllowed.into()),
|
None => return Json(Error::NotAllowed.into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if user.seller_data.account_id.is_some() {
|
||||||
|
return Json(Error::NotAllowed.into());
|
||||||
|
}
|
||||||
|
|
||||||
let client = match data.3 {
|
let client = match data.3 {
|
||||||
Some(ref c) => c,
|
Some(ref c) => c,
|
||||||
None => return Json(Error::Unknown.into()),
|
None => return Json(Error::Unknown.into()),
|
||||||
|
@ -420,3 +428,38 @@ pub async fn create_seller_account_request(
|
||||||
Err(e) => return Json(e.into()),
|
Err(e) => return Json(e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn login_link_request(
|
||||||
|
jar: CookieJar,
|
||||||
|
Extension(data): Extension<State>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
let data = &(data.read().await);
|
||||||
|
let user = match get_user_from_token!(jar, data.0) {
|
||||||
|
Some(ua) => ua,
|
||||||
|
None => return Json(Error::NotAllowed.into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
if user.seller_data.account_id.is_none() | !user.seller_data.completed_onboarding {
|
||||||
|
return Json(Error::NotAllowed.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let client = match data.3 {
|
||||||
|
Some(ref c) => c,
|
||||||
|
None => return Json(Error::Unknown.into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
match stripe::LoginLink::create(
|
||||||
|
&client,
|
||||||
|
&stripe::AccountId::from_str(&user.seller_data.account_id.unwrap()).unwrap(),
|
||||||
|
&data.0.0.0.host,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(x) => Json(ApiReturn {
|
||||||
|
ok: true,
|
||||||
|
message: "Acceptable".to_string(),
|
||||||
|
payload: Some(x.url),
|
||||||
|
}),
|
||||||
|
Err(e) => Json(Error::MiscError(e.to_string()).into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -520,6 +520,10 @@ pub fn routes() -> Router {
|
||||||
"/service_hooks/stripe/seller/onboarding",
|
"/service_hooks/stripe/seller/onboarding",
|
||||||
post(auth::connections::stripe::onboarding_account_link_request),
|
post(auth::connections::stripe::onboarding_account_link_request),
|
||||||
)
|
)
|
||||||
|
.route(
|
||||||
|
"/service_hooks/stripe/seller/login",
|
||||||
|
post(auth::connections::stripe::login_link_request),
|
||||||
|
)
|
||||||
// channels
|
// channels
|
||||||
.route("/channels", post(channels::channels::create_request))
|
.route("/channels", post(channels::channels::create_request))
|
||||||
.route(
|
.route(
|
||||||
|
|
95
crates/app/src/routes/pages/marketplace.rs
Normal file
95
crates/app/src/routes/pages/marketplace.rs
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
use super::render_error;
|
||||||
|
use crate::{assets::initial_context, get_lang, get_user_from_token, State};
|
||||||
|
use axum::{
|
||||||
|
response::{Html, IntoResponse},
|
||||||
|
Extension,
|
||||||
|
};
|
||||||
|
use axum_extra::extract::CookieJar;
|
||||||
|
use tetratto_core::model::Error;
|
||||||
|
|
||||||
|
/// `/settings/seller`
|
||||||
|
pub async fn seller_settings_request(
|
||||||
|
jar: CookieJar,
|
||||||
|
Extension(data): Extension<State>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
let data = data.read().await;
|
||||||
|
let user = match get_user_from_token!(jar, data.0) {
|
||||||
|
Some(ua) => ua,
|
||||||
|
None => {
|
||||||
|
return Err(Html(
|
||||||
|
render_error(Error::NotAllowed, &jar, &data, &None).await,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let lang = get_lang!(jar, data.0);
|
||||||
|
let context = initial_context(&data.0.0.0, lang, &Some(user)).await;
|
||||||
|
|
||||||
|
// return
|
||||||
|
Ok(Html(
|
||||||
|
data.1.render("marketplace/seller.html", &context).unwrap(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn connection_return_request(
|
||||||
|
jar: CookieJar,
|
||||||
|
Extension(data): Extension<State>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
let data = data.read().await;
|
||||||
|
let mut user = match get_user_from_token!(jar, data.0) {
|
||||||
|
Some(ua) => ua,
|
||||||
|
None => {
|
||||||
|
return Err(Html(
|
||||||
|
render_error(Error::NotAllowed, &jar, &data, &None).await,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// update user
|
||||||
|
user.seller_data.completed_onboarding = true;
|
||||||
|
if let Err(e) = data
|
||||||
|
.0
|
||||||
|
.update_user_seller_data(user.id, user.seller_data.clone())
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
return Err(Html(render_error(e, &jar, &data, &None).await));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
let lang = get_lang!(jar, data.0);
|
||||||
|
let mut context = initial_context(&data.0.0.0, lang, &Some(user)).await;
|
||||||
|
context.insert("connection_type", "return");
|
||||||
|
|
||||||
|
// return
|
||||||
|
Ok(Html(
|
||||||
|
data.1
|
||||||
|
.render("auth/seller_connection.html", &context)
|
||||||
|
.unwrap(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn connection_reload_request(
|
||||||
|
jar: CookieJar,
|
||||||
|
Extension(data): Extension<State>,
|
||||||
|
) -> impl IntoResponse {
|
||||||
|
let data = data.read().await;
|
||||||
|
let user = match get_user_from_token!(jar, data.0) {
|
||||||
|
Some(ua) => ua,
|
||||||
|
None => {
|
||||||
|
return Err(Html(
|
||||||
|
render_error(Error::NotAllowed, &jar, &data, &None).await,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let lang = get_lang!(jar, data.0);
|
||||||
|
let mut context = initial_context(&data.0.0.0, lang, &Some(user)).await;
|
||||||
|
context.insert("connection_type", "reload");
|
||||||
|
|
||||||
|
// return
|
||||||
|
Ok(Html(
|
||||||
|
data.1
|
||||||
|
.render("auth/seller_connection.html", &context)
|
||||||
|
.unwrap(),
|
||||||
|
))
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ pub mod developer;
|
||||||
pub mod forge;
|
pub mod forge;
|
||||||
pub mod journals;
|
pub mod journals;
|
||||||
pub mod littleweb;
|
pub mod littleweb;
|
||||||
|
pub mod marketplace;
|
||||||
pub mod misc;
|
pub mod misc;
|
||||||
pub mod mod_panel;
|
pub mod mod_panel;
|
||||||
pub mod profile;
|
pub mod profile;
|
||||||
|
@ -76,6 +77,14 @@ pub fn routes() -> Router {
|
||||||
"/auth/connections_link/app/{id}",
|
"/auth/connections_link/app/{id}",
|
||||||
get(developer::connection_callback_request),
|
get(developer::connection_callback_request),
|
||||||
)
|
)
|
||||||
|
.route(
|
||||||
|
"/auth/connections_link/seller/reload",
|
||||||
|
get(marketplace::connection_reload_request),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/auth/connections_link/seller/return",
|
||||||
|
get(marketplace::connection_return_request),
|
||||||
|
)
|
||||||
// profile
|
// profile
|
||||||
.route("/settings", get(profile::settings_request))
|
.route("/settings", get(profile::settings_request))
|
||||||
.route("/@{username}", get(profile::posts_request))
|
.route("/@{username}", get(profile::posts_request))
|
||||||
|
@ -146,6 +155,11 @@ pub fn routes() -> Router {
|
||||||
.route("/domains/{id}", get(littleweb::domain_request))
|
.route("/domains/{id}", get(littleweb::domain_request))
|
||||||
.route("/net", get(littleweb::browser_home_request))
|
.route("/net", get(littleweb::browser_home_request))
|
||||||
.route("/net/{*uri}", get(littleweb::browser_request))
|
.route("/net/{*uri}", get(littleweb::browser_request))
|
||||||
|
// marketplace
|
||||||
|
.route(
|
||||||
|
"/settings/seller",
|
||||||
|
get(marketplace::seller_settings_request),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lw_routes() -> Router {
|
pub fn lw_routes() -> Router {
|
||||||
|
|
|
@ -334,6 +334,8 @@ pub struct UserSettings {
|
||||||
pub struct StripeSellerData {
|
pub struct StripeSellerData {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub account_id: Option<String>,
|
pub account_id: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub completed_onboarding: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mime_avif() -> String {
|
fn mime_avif() -> String {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue