refactor wip

This commit is contained in:
Timur Gordon 2025-06-28 16:53:27 +02:00
parent c1ea9483d7
commit 6f8fb27221
2 changed files with 297 additions and 1 deletions

View File

@ -2,8 +2,10 @@ pub mod step_payment_stripe;
pub mod simple_resident_wizard; pub mod simple_resident_wizard;
pub mod simple_step_info; pub mod simple_step_info;
pub mod residence_card; pub mod residence_card;
pub mod refactored_resident_wizard;
pub use step_payment_stripe::*; pub use step_payment_stripe::*;
pub use simple_resident_wizard::*; pub use simple_resident_wizard::*;
pub use simple_step_info::*; pub use simple_step_info::*;
pub use residence_card::*; pub use residence_card::*;
pub use refactored_resident_wizard::*;

View File

@ -0,0 +1,294 @@
use yew::prelude::*;
use crate::models::company::{DigitalResidentFormData, DigitalResident};
use crate::services::ResidentService;
use crate::components::common::ui::progress_indicator::{ProgressIndicator, ProgressVariant, ProgressColor, ProgressSize};
use crate::components::common::ui::loading_spinner::LoadingSpinner;
use super::{SimpleStepInfo, StepPaymentStripe, ResidenceCard};
use web_sys::console;
#[derive(Properties, PartialEq)]
pub struct RefactoredResidentWizardProps {
pub on_registration_complete: Callback<DigitalResident>,
pub on_back_to_parent: Callback<()>,
#[prop_or_default]
pub success_resident_id: Option<u32>,
#[prop_or_default]
pub show_failure: bool,
}
pub enum RefactoredResidentWizardMsg {
NextStep,
PrevStep,
UpdateFormData(DigitalResidentFormData),
RegistrationComplete(DigitalResident),
RegistrationError(String),
}
pub struct RefactoredResidentWizard {
current_step: usize,
form_data: DigitalResidentFormData,
validation_errors: Vec<String>,
}
impl Component for RefactoredResidentWizard {
type Message = RefactoredResidentWizardMsg;
type Properties = RefactoredResidentWizardProps;
fn create(ctx: &Context<Self>) -> Self {
let current_step = if ctx.props().success_resident_id.is_some() {
2 // Success step
} else if ctx.props().show_failure {
1 // Payment step
} else {
0 // Start from beginning
};
Self {
current_step,
form_data: DigitalResidentFormData::default(),
validation_errors: Vec::new(),
}
}
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
RefactoredResidentWizardMsg::NextStep => {
// Simple validation for demo
if self.current_step == 0 {
if self.form_data.full_name.trim().is_empty() || self.form_data.email.trim().is_empty() {
self.validation_errors = vec!["Please fill in all required fields".to_string()];
return true;
}
}
self.validation_errors.clear();
if self.current_step < 2 {
self.current_step += 1;
}
true
}
RefactoredResidentWizardMsg::PrevStep => {
if self.current_step > 0 {
self.current_step -= 1;
}
true
}
RefactoredResidentWizardMsg::UpdateFormData(new_data) => {
self.form_data = new_data;
true
}
RefactoredResidentWizardMsg::RegistrationComplete(resident) => {
self.current_step = 2; // Move to success step
ctx.props().on_registration_complete.emit(resident);
true
}
RefactoredResidentWizardMsg::RegistrationError(error) => {
self.validation_errors = vec![error];
true
}
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
let link = ctx.link();
html! {
<div class="h-100 d-flex flex-column">
{if self.current_step < 2 {
html! {
<>
// Progress indicator using our generic component
<ProgressIndicator
current_step={self.current_step}
total_steps={2}
variant={ProgressVariant::Dots}
color={ProgressColor::Primary}
size={ProgressSize::Medium}
show_step_numbers={true}
/>
// Step content
<div class="flex-grow-1">
{self.render_current_step(ctx)}
</div>
// Navigation footer
{if self.current_step < 2 {
self.render_navigation_footer(ctx)
} else {
html! {}
}}
// Validation errors
{if !self.validation_errors.is_empty() {
html! {
<div class="alert alert-danger mt-3">
<ul class="mb-0">
{for self.validation_errors.iter().map(|error| {
html! { <li>{error}</li> }
})}
</ul>
</div>
}
} else {
html! {}
}}
</>
}
} else {
// Success step
html! {
<div class="flex-grow-1">
{self.render_success_step(ctx)}
</div>
}
}}
</div>
}
}
}
impl RefactoredResidentWizard {
fn render_current_step(&self, ctx: &Context<Self>) -> Html {
let link = ctx.link();
let on_form_update = link.callback(RefactoredResidentWizardMsg::UpdateFormData);
match self.current_step {
0 => html! {
<SimpleStepInfo
form_data={self.form_data.clone()}
on_change={on_form_update}
/>
},
1 => html! {
<StepPaymentStripe
form_data={self.form_data.clone()}
client_secret={Option::<String>::None}
processing_payment={false}
on_process_payment={link.callback(|_| RefactoredResidentWizardMsg::NextStep)}
on_payment_complete={link.callback(RefactoredResidentWizardMsg::RegistrationComplete)}
on_payment_error={link.callback(RefactoredResidentWizardMsg::RegistrationError)}
on_payment_plan_change={link.callback(|_| RefactoredResidentWizardMsg::NextStep)}
on_confirmation_change={link.callback(|_| RefactoredResidentWizardMsg::NextStep)}
/>
},
_ => html! { <div>{"Invalid step"}</div> }
}
}
fn render_navigation_footer(&self, ctx: &Context<Self>) -> Html {
let link = ctx.link();
html! {
<div class="card-footer">
<div class="d-flex justify-content-between align-items-center">
<div style="width: 120px;">
{if self.current_step > 0 {
html! {
<button
type="button"
class="btn btn-outline-secondary"
onclick={link.callback(|_| RefactoredResidentWizardMsg::PrevStep)}
>
<i class="bi bi-arrow-left me-1"></i>{"Previous"}
</button>
}
} else {
html! {}
}}
</div>
<div style="width: 150px;" class="text-end">
{if self.current_step == 0 {
html! {
<button
type="button"
class="btn btn-success"
onclick={link.callback(|_| RefactoredResidentWizardMsg::NextStep)}
>
{"Next"}<i class="bi bi-arrow-right ms-1"></i>
</button>
}
} else {
html! {}
}}
</div>
</div>
</div>
}
}
fn render_success_step(&self, ctx: &Context<Self>) -> Html {
html! {
<div class="text-center py-5">
<div class="mb-4">
<i class="bi bi-check-circle-fill text-success" style="font-size: 4rem;"></i>
</div>
<h2 class="text-success mb-3">{"Registration Successful!"}</h2>
<p class="lead mb-4">
{"Your digital resident registration has been successfully submitted and is now pending approval."}
</p>
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card border-success">
<div class="card-body">
<h5 class="card-title text-success">
<i class="bi bi-info-circle me-2"></i>{"What happens next?"}
</h5>
<div class="text-start">
<div class="d-flex align-items-start mb-3">
<div class="me-3">
<span class="badge bg-success rounded-pill">{"1"}</span>
</div>
<div>
<strong>{"Identity Verification"}</strong>
<p class="mb-0 text-muted">{"Our team will verify your identity and submitted documents."}</p>
</div>
</div>
<div class="d-flex align-items-start mb-3">
<div class="me-3">
<span class="badge bg-primary rounded-pill">{"2"}</span>
</div>
<div>
<strong>{"Background Check"}</strong>
<p class="mb-0 text-muted">{"We'll conduct necessary background checks and compliance verification."}</p>
</div>
</div>
<div class="d-flex align-items-start mb-3">
<div class="me-3">
<span class="badge bg-info rounded-pill">{"3"}</span>
</div>
<div>
<strong>{"Approval & Activation"}</strong>
<p class="mb-0 text-muted">{"Once approved, your digital resident status will be activated and you'll gain access to selected services."}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="mt-4">
<button
class="btn btn-success btn-lg"
onclick={ctx.props().on_back_to_parent.reform(|_| ())}
>
<i class="bi bi-list me-2"></i>{"View My Registrations"}
</button>
</div>
<div class="mt-4">
<div class="alert alert-info">
<i class="bi bi-envelope me-2"></i>
{"You will receive email updates about your registration status. The approval process typically takes 3-5 business days."}
</div>
</div>
</div>
}
}
}