portal, platform, and server fixes
This commit is contained in:
@@ -13,7 +13,7 @@ This guide covers the complete production setup for the Stripe Elements integrat
|
||||
- **Comprehensive error handling** and user guidance
|
||||
|
||||
### ✅ 2. Backend Server (`src/bin/server.rs`)
|
||||
- **Payment intent creation endpoint**: `/company/create-payment-intent`
|
||||
- **Payment intent creation endpoint**: `/api/company/create-payment-intent`
|
||||
- **Webhook handling**: `/webhooks/stripe`
|
||||
- **Payment success page**: `/company/payment-success`
|
||||
- **Health check**: `/api/health`
|
||||
@@ -232,7 +232,7 @@ cargo build --release --features server
|
||||
curl http://127.0.0.1:8080/api/health
|
||||
|
||||
# Test payment intent creation
|
||||
curl -X POST http://127.0.0.1:8080/company/create-payment-intent \
|
||||
curl -X POST http://127.0.0.1:8080/api/company/create-payment-intent \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"company_name":"Test","company_type":"Single FZC","payment_plan":"monthly","final_agreement":true,"agreements":["terms"]}'
|
||||
|
||||
|
@@ -183,7 +183,7 @@
|
||||
// Create payment intent on server
|
||||
window.createPaymentIntent = async function(formDataJson) {
|
||||
console.log('💳 Creating payment intent for company registration...');
|
||||
console.log('🔧 Server endpoint: /company/create-payment-intent');
|
||||
console.log('🔧 Server endpoint: /api/company/create-payment-intent');
|
||||
|
||||
try {
|
||||
// Parse the JSON string from Rust
|
||||
@@ -201,7 +201,7 @@
|
||||
final_agreement: formData.final_agreement
|
||||
});
|
||||
|
||||
const response = await fetch('http://127.0.0.1:3001/company/create-payment-intent', {
|
||||
const response = await fetch('http://127.0.0.1:3001/api/company/create-payment-intent', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -424,7 +424,7 @@
|
||||
};
|
||||
|
||||
console.log('✅ Stripe integration ready for company registration payments');
|
||||
console.log('🔧 Server endpoint: /company/create-payment-intent');
|
||||
console.log('🔧 Server endpoint: /api/company/create-payment-intent');
|
||||
console.log('💡 Navigate to Entities → Register Company → Step 4 to process payments');
|
||||
|
||||
// Add a test function for manual payment testing
|
||||
|
@@ -40,7 +40,7 @@ echo "✅ Build successful!"
|
||||
echo ""
|
||||
echo "🌐 Starting server on http://${HOST:-127.0.0.1}:${PORT:-8080}"
|
||||
echo "📊 Health check: http://${HOST:-127.0.0.1}:${PORT:-8080}/api/health"
|
||||
echo "💳 Payment endpoint: http://${HOST:-127.0.0.1}:${PORT:-8080}/company/create-payment-intent"
|
||||
echo "💳 Payment endpoint: http://${HOST:-127.0.0.1}:${PORT:-8080}/api/company/create-payment-intent"
|
||||
echo ""
|
||||
echo "🧪 To test the integration:"
|
||||
echo " 1. Open http://${HOST:-127.0.0.1}:${PORT:-8080} in your browser"
|
||||
|
@@ -491,7 +491,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
let app = Router::new()
|
||||
// API routes
|
||||
.route("/api/health", get(health_check))
|
||||
.route("/company/create-payment-intent", post(create_payment_intent))
|
||||
.route("/api/company/create-payment-intent", post(create_payment_intent))
|
||||
.route("/resident/create-payment-intent", post(create_resident_payment_intent))
|
||||
.route("/company/payment-success", get(payment_success))
|
||||
.route("/company/payment-failure", get(payment_failure))
|
||||
@@ -516,7 +516,7 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
info!("Starting server on {}", addr);
|
||||
info!("Health check: http://{}/api/health", addr);
|
||||
info!("Payment endpoint: http://{}/company/create-payment-intent", addr);
|
||||
info!("Payment endpoint: http://{}/api/company/create-payment-intent", addr);
|
||||
|
||||
// Start the server
|
||||
let listener = tokio::net::TcpListener::bind(&addr).await?;
|
||||
|
@@ -534,8 +534,8 @@ pub fn expenses_tab(props: &ExpensesTabProps) -> Html {
|
||||
// Expense Actions and Table
|
||||
<div class="row g-4">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-soft border-0">
|
||||
<div class="card-header bg-white border-bottom-0 py-3">
|
||||
<div class="card shadow-soft" style="border: none;">
|
||||
<div class="card-header bg-white py-3" style="border-bottom: none;">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5 class="mb-0 fw-bold">{"Expense Entries"}</h5>
|
||||
|
@@ -87,7 +87,7 @@ pub fn financial_reports_tab(props: &FinancialReportsTabProps) -> Html {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="card shadow-soft border-0">
|
||||
<div class="card shadow-soft" style="border: none;">
|
||||
<div class="card-body">
|
||||
if state.financial_reports.is_empty() {
|
||||
<div class="text-center py-5">
|
||||
|
@@ -28,7 +28,7 @@ pub fn overview_tab(props: &OverviewTabProps) -> Html {
|
||||
// Key Statistics Cards
|
||||
<div class="row g-4 mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card border-warning shadow-soft card-hover">
|
||||
<div class="card shadow-soft card-hover" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
@@ -47,7 +47,7 @@ pub fn overview_tab(props: &OverviewTabProps) -> Html {
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="card border-info shadow-soft card-hover">
|
||||
<div class="card shadow-soft card-hover" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
@@ -66,7 +66,7 @@ pub fn overview_tab(props: &OverviewTabProps) -> Html {
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="card border-success shadow-soft card-hover">
|
||||
<div class="card shadow-soft card-hover" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
@@ -85,7 +85,7 @@ pub fn overview_tab(props: &OverviewTabProps) -> Html {
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="card border-primary shadow-soft card-hover">
|
||||
<div class="card shadow-soft card-hover" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
@@ -107,8 +107,8 @@ pub fn overview_tab(props: &OverviewTabProps) -> Html {
|
||||
// Recent Transactions
|
||||
<div class="row g-4">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-soft border-0">
|
||||
<div class="card-header bg-white border-bottom-0 py-3">
|
||||
<div class="card shadow-soft" style="border: none;">
|
||||
<div class="card-header bg-white py-3" style="border-bottom: none;">
|
||||
<h5 class="mb-0 fw-bold">{"Recent Transactions"}</h5>
|
||||
<small class="text-muted">{"Latest payments made and received"}</small>
|
||||
</div>
|
||||
|
@@ -520,8 +520,8 @@ pub fn revenue_tab(props: &RevenueTabProps) -> Html {
|
||||
// Revenue Actions and Table
|
||||
<div class="row g-4">
|
||||
<div class="col-12">
|
||||
<div class="card shadow-soft border-0">
|
||||
<div class="card-header bg-white border-bottom-0 py-3">
|
||||
<div class="card shadow-soft" style="border: none;">
|
||||
<div class="card-header bg-white py-3" style="border-bottom: none;">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5 class="mb-0 fw-bold">{"Revenue Entries"}</h5>
|
||||
|
@@ -23,8 +23,8 @@ pub fn tax_tab(props: &TaxTabProps) -> Html {
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow-soft border-0">
|
||||
<div class="card-header bg-white border-bottom-0 py-3">
|
||||
<div class="card shadow-soft" style="border: none;">
|
||||
<div class="card-header bg-white py-3" style="border-bottom: none;">
|
||||
<h5 class="mb-0 fw-bold">{"Tax Summary"}</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -62,8 +62,8 @@ pub fn tax_tab(props: &TaxTabProps) -> Html {
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
<div class="card shadow-soft border-0">
|
||||
<div class="card-header bg-white border-bottom-0 py-3">
|
||||
<div class="card shadow-soft" style="border: none;">
|
||||
<div class="card-header bg-white py-3" style="border-bottom: none;">
|
||||
<h5 class="mb-0 fw-bold">{"Tax Actions"}</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
@@ -121,13 +121,13 @@ pub fn inbox(props: &InboxProps) -> Html {
|
||||
<style>
|
||||
{r#"
|
||||
.inbox-card {
|
||||
border: 1px solid #e9ecef;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
||||
}
|
||||
.inbox-card:hover {
|
||||
border-color: #dee2e6;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.12);
|
||||
}
|
||||
.notification-item {
|
||||
border-radius: 8px;
|
||||
|
@@ -50,11 +50,41 @@ pub fn header(props: &HeaderProps) -> Html {
|
||||
<i class="bi bi-list"></i>
|
||||
</button>
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="bi bi-building-gear text-primary fs-4 me-2"></i>
|
||||
<div>
|
||||
<h5 class="mb-0 fw-bold">{"Zanzibar Digital Freezone"}</h5>
|
||||
// Enhanced title with better typography
|
||||
<div class="ml-4 d-flex align-items-baseline">
|
||||
<h4 class="mb-0 me-2" style="
|
||||
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 1.35rem;
|
||||
background: linear-gradient(135deg, #0099FF 0%, #00CC66 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1.2;
|
||||
">
|
||||
{"Zanzibar"}
|
||||
</h4>
|
||||
</div>
|
||||
<div style="
|
||||
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
|
||||
font-weight: 500;
|
||||
font-size: 0.9rem;
|
||||
color: #6c757d;
|
||||
letter-spacing: 0.3px;
|
||||
margin-top: -2px;
|
||||
">
|
||||
{"DIGITAL FREEZONE"}
|
||||
</div>
|
||||
{if let Some(entity) = entity_name {
|
||||
html! { <small class="text-info">{entity}</small> }
|
||||
html! {
|
||||
<small class="text-info d-block" style="
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
margin-top: 1px;
|
||||
">{entity}</small>
|
||||
}
|
||||
} else {
|
||||
html! {}
|
||||
}}
|
||||
|
@@ -143,8 +143,31 @@ impl ResidentLandingOverlay {
|
||||
<div class="mb-4">
|
||||
<i class="bi bi-globe2" style="font-size: 4rem; opacity: 0.9;"></i>
|
||||
</div>
|
||||
<h1 class="display-4 fw-bold mb-4">
|
||||
{"Zanzibar Digital Freezone"}
|
||||
<h1 class="display-4 mb-4" style="
|
||||
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1.1;
|
||||
">
|
||||
<span style="
|
||||
background: linear-gradient(135deg, rgba(255,255,255,0.95) 0%, rgba(255,255,255,0.8) 100%);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
text-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
">
|
||||
{"Zanzibar"}
|
||||
</span>
|
||||
<br/>
|
||||
<span style="
|
||||
font-size: 0.7em;
|
||||
font-weight: 500;
|
||||
letter-spacing: 2px;
|
||||
color: rgba(255,255,255,0.9);
|
||||
text-transform: uppercase;
|
||||
">
|
||||
{"Digital Freezone"}
|
||||
</span>
|
||||
</h1>
|
||||
<h2 class="h3 mb-4 text-white-75">
|
||||
{"Your Gateway to Digital Residency"}
|
||||
|
@@ -42,7 +42,7 @@ pub fn view_component(props: &ViewComponentProps) -> Html {
|
||||
};
|
||||
|
||||
html! {
|
||||
<div class="container-fluid" style="max-width: 1100px;">
|
||||
<div class="container-fluid" style="max-width: 1400px;">
|
||||
<div class="px-3 px-md-4 px-lg-5 px-xl-6">
|
||||
// Breadcrumbs (if provided)
|
||||
if let Some(breadcrumbs) = &props.breadcrumbs {
|
||||
@@ -69,7 +69,7 @@ pub fn view_component(props: &ViewComponentProps) -> Html {
|
||||
// Left side: Title and description
|
||||
<div>
|
||||
if let Some(title) = &props.title {
|
||||
<h2 class="mb-1 fw-bold">{title}</h2>
|
||||
<h2 class="mb-1">{title}</h2>
|
||||
}
|
||||
if let Some(description) = &props.description {
|
||||
<p class="text-muted mb-0">{description}</p>
|
||||
@@ -87,8 +87,8 @@ pub fn view_component(props: &ViewComponentProps) -> Html {
|
||||
|
||||
// Modern tabs navigation (if provided)
|
||||
if let Some(tabs) = &props.tabs {
|
||||
<div class="mb-0">
|
||||
<ul class="nav nav-tabs border-bottom-0" role="tablist">
|
||||
<div class="mb-4">
|
||||
<div class="bg-white rounded-3 shadow-sm p-2 d-inline-flex">
|
||||
{for tabs.keys().map(|tab_name| {
|
||||
let is_active = *active_tab == *tab_name;
|
||||
let tab_name_clone = tab_name.clone();
|
||||
@@ -102,34 +102,27 @@ pub fn view_component(props: &ViewComponentProps) -> Html {
|
||||
};
|
||||
|
||||
html! {
|
||||
<li class="nav-item" role="presentation">
|
||||
<button
|
||||
class={classes!(
|
||||
"nav-link",
|
||||
"px-3",
|
||||
"py-2",
|
||||
"small",
|
||||
"border",
|
||||
"border-bottom-0",
|
||||
"bg-light",
|
||||
"text-muted",
|
||||
if is_active {
|
||||
"active bg-white text-dark border-primary border-bottom-0"
|
||||
} else {
|
||||
"border-light"
|
||||
}
|
||||
)}
|
||||
type="button"
|
||||
role="tab"
|
||||
onclick={on_click}
|
||||
style={if is_active { "margin-bottom: -1px; z-index: 1; position: relative;" } else { "" }}
|
||||
>
|
||||
{tab_name}
|
||||
</button>
|
||||
</li>
|
||||
<button
|
||||
class={classes!(
|
||||
"btn",
|
||||
"btn-sm",
|
||||
"me-1",
|
||||
"border-0",
|
||||
"small",
|
||||
if is_active {
|
||||
"bg-light text-dark"
|
||||
} else {
|
||||
"bg-transparent text-muted"
|
||||
}
|
||||
)}
|
||||
type="button"
|
||||
onclick={on_click}
|
||||
>
|
||||
{tab_name}
|
||||
</button>
|
||||
}
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
} else {
|
||||
@@ -199,7 +192,7 @@ pub fn view_component(props: &ViewComponentProps) -> Html {
|
||||
|
||||
// Tab Content (if tabs are provided)
|
||||
if let Some(tabs) = &props.tabs {
|
||||
<div class="tab-content border border-top-0 rounded-bottom bg-white p-4">
|
||||
<div class="tab-content">
|
||||
{for tabs.iter().map(|(tab_name, content)| {
|
||||
let is_active = *active_tab == *tab_name;
|
||||
html! {
|
||||
|
@@ -123,7 +123,7 @@ impl AppView {
|
||||
AppView::Login => "Login".to_string(),
|
||||
AppView::Home => "Home".to_string(),
|
||||
AppView::Administration => "Administration".to_string(),
|
||||
AppView::PersonAdministration => "Administration".to_string(),
|
||||
AppView::PersonAdministration => "Settings".to_string(),
|
||||
AppView::Business => "Business".to_string(),
|
||||
AppView::Accounting => "Accounting".to_string(),
|
||||
AppView::Contracts => "Contracts".to_string(),
|
||||
|
@@ -261,7 +261,7 @@ impl CompaniesView {
|
||||
let link = ctx.link();
|
||||
|
||||
html! {
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<div class="d-flex align-items-center">
|
||||
|
@@ -297,7 +297,7 @@ impl ContractsViewComponent {
|
||||
// Filters Section
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-primary bg-opacity-10 rounded-3 p-2 me-3">
|
||||
@@ -348,7 +348,7 @@ impl ContractsViewComponent {
|
||||
// Contracts Table
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-success bg-opacity-10 rounded-3 p-2 me-3">
|
||||
@@ -449,7 +449,7 @@ impl ContractsViewComponent {
|
||||
html! {
|
||||
<div class="row">
|
||||
<div class="col-lg-8">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center mb-4">
|
||||
<div class="bg-primary bg-opacity-10 rounded-3 p-2 me-3">
|
||||
@@ -541,7 +541,7 @@ Payment will be made according to the following schedule:
|
||||
</div>
|
||||
|
||||
<div class="col-lg-4">
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card shadow-sm mb-4" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-info bg-opacity-10 rounded-3 p-2 me-3">
|
||||
@@ -560,7 +560,7 @@ Payment will be made according to the following schedule:
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-warning bg-opacity-10 rounded-3 p-2 me-3">
|
||||
|
@@ -152,6 +152,7 @@ impl Component for EntitiesView {
|
||||
<ViewComponent
|
||||
title={Some("Registration Successful".to_string())}
|
||||
description={Some("Your company registration has been completed successfully".to_string())}
|
||||
use_modern_header={true}
|
||||
>
|
||||
<RegistrationWizard
|
||||
on_registration_complete={link.callback(EntitiesViewMsg::RegistrationComplete)}
|
||||
@@ -170,6 +171,7 @@ impl Component for EntitiesView {
|
||||
<ViewComponent
|
||||
title={Some("Register New Company".to_string())}
|
||||
description={Some("Complete the registration process to create your new company".to_string())}
|
||||
use_modern_header={true}
|
||||
>
|
||||
<RegistrationWizard
|
||||
on_registration_complete={link.callback(EntitiesViewMsg::RegistrationComplete)}
|
||||
@@ -198,6 +200,7 @@ impl Component for EntitiesView {
|
||||
description={Some("Manage your companies and registrations".to_string())}
|
||||
tabs={Some(tabs)}
|
||||
default_tab={Some("Companies".to_string())}
|
||||
use_modern_header={true}
|
||||
/>
|
||||
}
|
||||
}
|
||||
@@ -255,7 +258,7 @@ impl EntitiesView {
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
// Header with new registration button
|
||||
<div class="card mb-4">
|
||||
<div class="card mb-4 shadow-sm" style="border: none;">
|
||||
<div class="card-body text-center py-4">
|
||||
<div class="mb-3">
|
||||
<i class="bi bi-plus-circle-fill text-success" style="font-size: 3rem;"></i>
|
||||
@@ -290,7 +293,7 @@ impl EntitiesView {
|
||||
|
||||
if self.registrations.is_empty() {
|
||||
return html! {
|
||||
<div class="card">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">
|
||||
<i class="bi bi-file-earmark-text me-2"></i>{"Pending Registrations"}
|
||||
@@ -306,7 +309,7 @@ impl EntitiesView {
|
||||
}
|
||||
|
||||
html! {
|
||||
<div class="card">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h5 class="mb-0">
|
||||
|
@@ -273,7 +273,7 @@ pub fn person_administration_view(props: &PersonAdministrationViewProps) -> Html
|
||||
|
||||
// Account Settings Tab (Person-specific)
|
||||
tabs.insert("Account Settings".to_string(), html! {
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center mb-4">
|
||||
<div class="bg-primary bg-opacity-10 rounded-3 p-3 me-3">
|
||||
@@ -327,7 +327,7 @@ pub fn person_administration_view(props: &PersonAdministrationViewProps) -> Html
|
||||
|
||||
// Privacy & Security Tab
|
||||
tabs.insert("Privacy & Security".to_string(), html! {
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center mb-4">
|
||||
<div class="bg-success bg-opacity-10 rounded-3 p-3 me-3">
|
||||
@@ -393,7 +393,7 @@ pub fn person_administration_view(props: &PersonAdministrationViewProps) -> Html
|
||||
<div class="row">
|
||||
// Subscription Tier Pane
|
||||
<div class="col-lg-4 mb-4">
|
||||
<div class="card border-0 shadow-sm h-100">
|
||||
<div class="card shadow-sm h-100" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-warning bg-opacity-10 rounded-3 p-2 me-3">
|
||||
@@ -446,7 +446,7 @@ pub fn person_administration_view(props: &PersonAdministrationViewProps) -> Html
|
||||
|
||||
<div class="col-lg-8">
|
||||
// Payments Table Pane
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card shadow-sm mb-4" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-info bg-opacity-10 rounded-3 p-2 me-3">
|
||||
@@ -491,7 +491,7 @@ pub fn person_administration_view(props: &PersonAdministrationViewProps) -> Html
|
||||
</div>
|
||||
|
||||
// Payment Methods Pane
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-body p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<div class="d-flex align-items-center">
|
||||
@@ -516,7 +516,7 @@ pub fn person_administration_view(props: &PersonAdministrationViewProps) -> Html
|
||||
<div class="row">
|
||||
{for billing_api.payment_methods.iter().map(|method| html! {
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card border">
|
||||
<div class="card shadow-sm" style="border: none;">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-start">
|
||||
<div class="d-flex align-items-center">
|
||||
@@ -578,26 +578,13 @@ pub fn person_administration_view(props: &PersonAdministrationViewProps) -> Html
|
||||
|
||||
html! {
|
||||
<>
|
||||
<div class="container-fluid px-3 px-md-4 px-lg-5 px-xl-6">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h1 class="h3 mb-1">{"Settings"}</h1>
|
||||
<p class="text-muted mb-0">{"Manage your account settings and preferences"}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ViewComponent
|
||||
title={None::<String>}
|
||||
description={None::<String>}
|
||||
tabs={Some(tabs)}
|
||||
default_tab={Some("Account Settings".to_string())}
|
||||
use_modern_header={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ViewComponent
|
||||
title={Some("Settings".to_string())}
|
||||
description={Some("Manage your account settings and preferences".to_string())}
|
||||
tabs={Some(tabs)}
|
||||
default_tab={Some("Account Settings".to_string())}
|
||||
use_modern_header={true}
|
||||
/>
|
||||
|
||||
// Plan Selection Modal
|
||||
if *show_plan_modal {
|
||||
|
@@ -77,6 +77,7 @@ body {
|
||||
z-index: 1030;
|
||||
background-color: #212529 !important;
|
||||
color: white;
|
||||
border-bottom: var(--bs-border-width) var(--bs-border-style) var(--bs-border-color) !important;
|
||||
}
|
||||
|
||||
.header .container-fluid {
|
||||
|
@@ -155,7 +155,7 @@ window.createPaymentIntent = async function(formDataJson) {
|
||||
|
||||
console.log('Form data:', formData);
|
||||
|
||||
const response = await fetch('/company/create-payment-intent', {
|
||||
const response = await fetch('/api/company/create-payment-intent', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
Reference in New Issue
Block a user