277 lines
14 KiB
Rust
277 lines
14 KiB
Rust
use yew::prelude::*;
|
|
use web_sys::HtmlInputElement;
|
|
use crate::models::*;
|
|
|
|
#[derive(Properties, PartialEq)]
|
|
pub struct StepOneProps {
|
|
pub form_data: CompanyFormData,
|
|
pub on_form_update: Callback<CompanyFormData>,
|
|
}
|
|
|
|
pub enum StepOneMsg {
|
|
UpdateCompanyName(String),
|
|
UpdateDescription(String),
|
|
UpdateEmail(String),
|
|
UpdateIndustry(String),
|
|
SelectCompanyType(CompanyType),
|
|
}
|
|
|
|
pub struct StepOne {
|
|
form_data: CompanyFormData,
|
|
}
|
|
|
|
impl Component for StepOne {
|
|
type Message = StepOneMsg;
|
|
type Properties = StepOneProps;
|
|
|
|
fn create(ctx: &Context<Self>) -> Self {
|
|
Self {
|
|
form_data: ctx.props().form_data.clone(),
|
|
}
|
|
}
|
|
|
|
fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
|
|
match msg {
|
|
StepOneMsg::UpdateCompanyName(value) => {
|
|
self.form_data.company_name = value;
|
|
}
|
|
StepOneMsg::UpdateDescription(value) => {
|
|
self.form_data.company_purpose = Some(value);
|
|
}
|
|
StepOneMsg::UpdateEmail(value) => {
|
|
self.form_data.company_email = value;
|
|
}
|
|
StepOneMsg::UpdateIndustry(value) => {
|
|
self.form_data.company_industry = if value.is_empty() { None } else { Some(value) };
|
|
}
|
|
StepOneMsg::SelectCompanyType(company_type) => {
|
|
self.form_data.company_type = company_type;
|
|
}
|
|
}
|
|
|
|
// Notify parent of form data changes
|
|
ctx.props().on_form_update.emit(self.form_data.clone());
|
|
true
|
|
}
|
|
|
|
fn changed(&mut self, ctx: &Context<Self>, _old_props: &Self::Properties) -> bool {
|
|
self.form_data = ctx.props().form_data.clone();
|
|
true
|
|
}
|
|
|
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
|
let link = ctx.link();
|
|
|
|
html! {
|
|
<div class="step-content">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<div class="row mb-3">
|
|
<label for="companyName" class="col-sm-4 col-form-label" data-bs-toggle="tooltip" data-bs-placement="top" title="The official name of your company or legal entity">
|
|
{"Company Name"} <span class="text-danger">{"*"}</span>
|
|
</label>
|
|
<div class="col-sm-8">
|
|
<input
|
|
type="text"
|
|
class="form-control"
|
|
id="companyName"
|
|
placeholder="Enter company name"
|
|
value={self.form_data.company_name.clone()}
|
|
oninput={link.callback(|e: InputEvent| {
|
|
let input: HtmlInputElement = e.target_unchecked_into();
|
|
StepOneMsg::UpdateCompanyName(input.value())
|
|
})}
|
|
required=true
|
|
data-bs-toggle="tooltip"
|
|
data-bs-placement="top"
|
|
title="The official name of your company or legal entity"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<label for="email" class="col-sm-4 col-form-label" data-bs-toggle="tooltip" data-bs-placement="top" title="Primary contact email for the company">
|
|
{"Email Address"} <span class="text-danger">{"*"}</span>
|
|
</label>
|
|
<div class="col-sm-8">
|
|
<input
|
|
type="email"
|
|
class="form-control"
|
|
id="email"
|
|
placeholder="company@example.com"
|
|
value={self.form_data.company_email.clone()}
|
|
oninput={link.callback(|e: InputEvent| {
|
|
let input: HtmlInputElement = e.target_unchecked_into();
|
|
StepOneMsg::UpdateEmail(input.value())
|
|
})}
|
|
required=true
|
|
data-bs-toggle="tooltip"
|
|
data-bs-placement="top"
|
|
title="Primary contact email for the company"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row mb-3">
|
|
<label for="industry" class="col-sm-4 col-form-label" data-bs-toggle="tooltip" data-bs-placement="top" title="Primary industry sector (optional)">
|
|
{"Industry"}
|
|
</label>
|
|
<div class="col-sm-8">
|
|
<select
|
|
class="form-select"
|
|
id="industry"
|
|
value={self.form_data.company_industry.clone().unwrap_or_default()}
|
|
onchange={link.callback(|e: Event| {
|
|
let input: HtmlInputElement = e.target_unchecked_into();
|
|
StepOneMsg::UpdateIndustry(input.value())
|
|
})}
|
|
data-bs-toggle="tooltip"
|
|
data-bs-placement="top"
|
|
title="Primary industry sector (optional)"
|
|
>
|
|
<option value="">{"Select industry"}</option>
|
|
<option value="Technology">{"Technology"}</option>
|
|
<option value="Finance">{"Finance"}</option>
|
|
<option value="Healthcare">{"Healthcare"}</option>
|
|
<option value="Education">{"Education"}</option>
|
|
<option value="Retail">{"Retail"}</option>
|
|
<option value="Manufacturing">{"Manufacturing"}</option>
|
|
<option value="Real Estate">{"Real Estate"}</option>
|
|
<option value="Consulting">{"Consulting"}</option>
|
|
<option value="Media">{"Media"}</option>
|
|
<option value="Transportation">{"Transportation"}</option>
|
|
<option value="Energy">{"Energy"}</option>
|
|
<option value="Agriculture">{"Agriculture"}</option>
|
|
<option value="Other">{"Other"}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="mb-3">
|
|
<textarea
|
|
class="form-control"
|
|
id="description"
|
|
rows="5"
|
|
placeholder="Describe your company's business activities and purpose..."
|
|
value={self.form_data.company_purpose.clone().unwrap_or_default()}
|
|
oninput={link.callback(|e: InputEvent| {
|
|
let input: HtmlInputElement = e.target_unchecked_into();
|
|
StepOneMsg::UpdateDescription(input.value())
|
|
})}
|
|
data-bs-toggle="tooltip"
|
|
data-bs-placement="top"
|
|
title="Brief description of your company's business activities and purpose"
|
|
></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
// Company Type Selection
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<div class="row">
|
|
{self.render_company_type_option(ctx, CompanyType::SingleFZC,
|
|
"Single FZC",
|
|
"Perfect for individual entrepreneurs and solo ventures. Simple structure with one shareholder.",
|
|
vec!["1 shareholder only", "Cannot issue digital assets", "Can hold external shares", "Connect to bank", "Participate in ecosystem"],
|
|
"$20 setup + $20/month")}
|
|
|
|
{self.render_company_type_option(ctx, CompanyType::StartupFZC,
|
|
"Startup FZC",
|
|
"Ideal for small teams and early-stage startups. Allows multiple shareholders and digital asset issuance.",
|
|
vec!["Up to 5 shareholders", "Can issue digital assets", "Hold external shares", "Connect to bank", "Full ecosystem access"],
|
|
"$50 setup + $50/month")}
|
|
|
|
{self.render_company_type_option(ctx, CompanyType::GrowthFZC,
|
|
"Growth FZC",
|
|
"Designed for growing businesses that need more flexibility and can hold physical assets.",
|
|
vec!["Up to 20 shareholders", "Can issue digital assets", "Hold external shares", "Connect to bank", "Hold physical assets"],
|
|
"$100 setup + $100/month")}
|
|
|
|
{self.render_company_type_option(ctx, CompanyType::GlobalFZC,
|
|
"Global FZC",
|
|
"Enterprise-level structure for large organizations with unlimited shareholders and full capabilities.",
|
|
vec!["Unlimited shareholders", "Can issue digital assets", "Hold external shares", "Connect to bank", "Hold physical assets"],
|
|
"$2000 setup + $200/month")}
|
|
|
|
{self.render_company_type_option(ctx, CompanyType::CooperativeFZC,
|
|
"Cooperative FZC",
|
|
"Democratic organization structure with collective decision-making and equitable distribution.",
|
|
vec!["Unlimited members", "Democratic governance", "Collective decision-making", "Equitable distribution", "Full capabilities"],
|
|
"$2000 setup + $200/month")}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
}
|
|
}
|
|
}
|
|
|
|
impl StepOne {
|
|
fn render_company_type_option(
|
|
&self,
|
|
ctx: &Context<Self>,
|
|
company_type: CompanyType,
|
|
title: &str,
|
|
description: &str,
|
|
benefits: Vec<&str>,
|
|
price: &str,
|
|
) -> Html {
|
|
let link = ctx.link();
|
|
let is_selected = self.form_data.company_type == company_type;
|
|
let card_class = if is_selected {
|
|
"card border-success mb-3 shadow-sm"
|
|
} else {
|
|
"card border-light mb-3"
|
|
};
|
|
|
|
html! {
|
|
<div class="col-xl col-lg-4 col-md-6 mb-3" style="min-width: 220px; max-width: 280px;">
|
|
<div class={card_class} style="cursor: pointer;" onclick={link.callback(move |_| StepOneMsg::SelectCompanyType(company_type.clone()))}>
|
|
<div class="card-header">
|
|
<div class="d-flex align-items-center">
|
|
<input
|
|
type="radio"
|
|
class="form-check-input me-2"
|
|
checked={is_selected}
|
|
onchange={link.callback(move |_| StepOneMsg::SelectCompanyType(company_type.clone()))}
|
|
/>
|
|
<h6 class="mb-0">{title}</h6>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<p class="card-text text-muted mb-2">{description}</p>
|
|
<div class="text-left mb-3">
|
|
<span class="badge bg-primary">{price}</span>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<h6 class="text-success mb-2">{"Key Features:"}</h6>
|
|
<ul class="list-unstyled mb-0">
|
|
{for benefits.iter().map(|benefit| {
|
|
html! {
|
|
<li class="mb-1">
|
|
<i class="bi bi-check-circle text-success me-2"></i>{benefit}
|
|
</li>
|
|
}
|
|
})}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{if is_selected {
|
|
html! {
|
|
<div class="card-footer bg-success text-white">
|
|
<i class="bi bi-check-circle me-2"></i>{"Selected"}
|
|
</div>
|
|
}
|
|
} else {
|
|
html! {}
|
|
}}
|
|
</div>
|
|
</div>
|
|
}
|
|
}
|
|
} |