1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-03-21 12:29:03 +01:00

(ui) Plan form layout

This commit is contained in:
vincent 2023-01-24 09:47:01 +01:00 committed by Sylvain
parent 587dcda5d5
commit 9294bc4c88
9 changed files with 257 additions and 174 deletions

View File

@ -24,6 +24,7 @@ import { UserPlus } from 'phosphor-react';
import { PartnerModal } from './partner-modal';
import { PlanPricingForm } from './plan-pricing-form';
import { AdvancedAccountingForm } from '../accounting/advanced-accounting-form';
import { FabTabs } from '../base/fab-tabs';
declare const Application: IApplication;
@ -130,140 +131,195 @@ export const PlanForm: React.FC<PlanFormProps> = ({ action, plan, onError, onSuc
setValue('partner_id', user.id);
};
return (
<div className="plan-form">
<form onSubmit={handleSubmit(onSubmit)}>
<h4>{t('app.admin.plan_form.general_information')}</h4>
<FormInput register={register}
id="base_name"
formState={formState}
rules={{
required: true,
maxLength: { value: 24, message: t('app.admin.plan_form.name_max_length') }
}}
label={t('app.admin.plan_form.name')} />
{action === 'create' && <FormSwitch control={control}
formState={formState}
onChange={handleAllGroupsChange}
defaultValue={false}
label={t('app.admin.plan_form.transversal')}
tooltip={t('app.admin.plan_form.transversal_help')}
id="all_groups" />}
{!allGroups && groups && <FormSelect options={groups}
formState={formState}
control={control}
rules={{ required: !allGroups }}
disabled={action === 'update'}
label={t('app.admin.plan_form.group')}
id="group_id" />}
{categories?.length > 0 && <FormSelect options={categories}
formState={formState}
control={control}
id="plan_category_id"
tooltip={t('app.admin.plan_form.category_help')}
label={t('app.admin.plan_form.category')} />}
{action === 'update' && <FabAlert level="warning">
{t('app.admin.plan_form.edit_amount_info')}
</FabAlert>}
<FormInput register={register}
formState={formState}
id="amount"
type="number"
step={0.01}
addOn={FormatLib.currencySymbol()}
rules={{ required: true, min: 0 }}
label={t('app.admin.plan_form.subscription_price')} />
<FormInput register={register}
formState={formState}
id="ui_weight"
type="number"
label={t('app.admin.plan_form.visual_prominence')}
tooltip={t('app.admin.plan_form.visual_prominence_help')} />
<FormSwitch control={control}
formState={formState}
id="is_rolling"
label={t('app.admin.plan_form.rolling_subscription')}
disabled={action === 'update'}
tooltip={t('app.admin.plan_form.rolling_subscription_help')} />
<FormSwitch control={control}
formState={formState}
id="monthly_payment"
label={t('app.admin.plan_form.monthly_payment')}
disabled={action === 'update' || output.interval === 'week'}
tooltip={t('app.admin.plan_form.monthly_payment_help')} />
<FormRichText control={control}
formState={formState}
id="description"
label={t('app.admin.plan_form.description')}
limit={200}
heading link blockquote />
<FormFileUpload setValue={setValue}
register={register}
formState={formState}
defaultFile={output.plan_file_attributes}
id="plan_file_attributes"
className="plan-sheet"
label={t('app.admin.plan_form.information_sheet')} />
<FormSwitch control={control}
formState={formState}
id="disabled"
defaultValue={false}
label={t('app.admin.plan_form.disabled')}
tooltip={t('app.admin.plan_form.disabled_help')} />
<h4>{t('app.admin.plan_form.duration')}</h4>
<div className="duration">
/**
* Render the content of the 'subscriptions settings' tab
*/
const renderSettingsTab = () => (
<div className='plan-form-content'>
<section>
<header>
<p className="title">{t('app.admin.plan_form.description')}</p>
</header>
<div className="content">
<FormInput register={register}
rules={{ required: true, min: 1 }}
disabled={action === 'update'}
id="base_name"
formState={formState}
label={t('app.admin.plan_form.number_of_periods')}
type="number"
id="interval_count" />
<FormSelect options={buildPeriodsOptions()}
control={control}
disabled={action === 'update'}
onChange={handlePeriodUpdate}
id="interval"
label={t('app.admin.plan_form.period')}
formState={formState}
rules={{ required: true }} />
rules={{
required: true,
maxLength: { value: 24, message: t('app.admin.plan_form.name_max_length') }
}}
label={t('app.admin.plan_form.name')} />
<FormRichText control={control}
formState={formState}
id="description"
label={t('app.admin.plan_form.description')}
limit={200}
heading link blockquote />
<FormFileUpload setValue={setValue}
register={register}
formState={formState}
defaultFile={output.plan_file_attributes}
id="plan_file_attributes"
className="plan-sheet"
label={t('app.admin.plan_form.information_sheet')} />
</div>
<h4>{t('app.admin.plan_form.partnership')}</h4>
<div className="partnership">
</section>
<section>
<header>
<p className="title">{t('app.admin.plan_form.general_settings')}</p>
<p className="description">{t('app.admin.plan_form.general_settings_info')}</p>
</header>
<div className="content">
{action === 'create' && <FormSwitch control={control}
formState={formState}
onChange={handleAllGroupsChange}
defaultValue={false}
label={t('app.admin.plan_form.transversal')}
tooltip={t('app.admin.plan_form.transversal_help')}
id="all_groups" />}
{!allGroups && groups && <FormSelect options={groups}
formState={formState}
control={control}
rules={{ required: !allGroups }}
disabled={action === 'update'}
label={t('app.admin.plan_form.group')}
id="group_id" />}
<div className="grp">
<FormInput register={register}
rules={{ required: true, min: 1 }}
disabled={action === 'update'}
formState={formState}
label={t('app.admin.plan_form.number_of_periods')}
type="number"
id="interval_count" />
<FormSelect options={buildPeriodsOptions()}
control={control}
disabled={action === 'update'}
onChange={handlePeriodUpdate}
id="interval"
label={t('app.admin.plan_form.period')}
formState={formState}
rules={{ required: true }} />
</div>
<FormInput register={register}
formState={formState}
id="amount"
type="number"
step={0.01}
addOn={FormatLib.currencySymbol()}
rules={{ required: true, min: 0 }}
label={t('app.admin.plan_form.subscription_price')} />
</div>
</section>
<section>
<header>
<p className="title">{t('app.admin.plan_form.activation_and_payment')}</p>
</header>
<div className="content">
<FormSwitch control={control}
formState={formState}
id="disabled"
defaultValue={false}
label={t('app.admin.plan_form.disabled')}
tooltip={t('app.admin.plan_form.disabled_help')} />
<FormSwitch control={control}
formState={formState}
id="is_rolling"
label={t('app.admin.plan_form.rolling_subscription')}
disabled={action === 'update'}
tooltip={t('app.admin.plan_form.rolling_subscription_help')} />
<FormSwitch control={control}
formState={formState}
id="monthly_payment"
label={t('app.admin.plan_form.monthly_payment')}
disabled={action === 'update' || output.interval === 'week'}
tooltip={t('app.admin.plan_form.monthly_payment_help')} />
</div>
</section>
<section>
<header>
<p className="title">{t('app.admin.plan_form.partnership')}</p>
<p className="description">{t('app.admin.plan_form.partner_plan_help')}</p>
</header>
<div className="content">
<FormSwitch control={control}
id="partnership"
disabled={action === 'update'}
tooltip={t('app.admin.plan_form.partner_plan_help')}
defaultValue={plan?.type === 'PartnerPlan'}
onChange={handlePartnershipChange}
formState={formState}
label={t('app.admin.plan_form.partner_plan')} />
<FormInput register={register} type="hidden" id="type" defaultValue="Plan" />
{output.type === 'PartnerPlan' && <div className="partner">
<FabButton className="add-partner is-info" icon={<UserPlus size={20} />} onClick={tooglePartnerModal}>
{partners && <FormSelect id="partner_id"
options={partners}
control={control}
formState={formState}
rules={{ required: output.type === 'PartnerPlan' }}
tooltip={t('app.admin.plan_form.alert_partner_notification')}
label={t('app.admin.plan_form.notified_partner')} />}
<FabButton className="is-secondary" icon={<UserPlus size={20} />} onClick={tooglePartnerModal}>
{t('app.admin.plan_form.new_user')}
</FabButton>
{partners && <FormSelect id="partner_id"
options={partners}
control={control}
formState={formState}
rules={{ required: output.type === 'PartnerPlan' }}
label={t('app.admin.plan_form.notified_partner')} />}
{output.partner_id && <FabAlert level="info">
{t('app.admin.plan_form.alert_partner_notification')}
</FabAlert>}
</div>}
</div>
<AdvancedAccountingForm register={register} onError={onError} />
{action === 'update' && <PlanPricingForm formState={formState}
control={control}
onError={onError}
setValue={setValue}
register={register} />}
<FabButton type="submit" className="is-info submit-btn">
{t('app.admin.plan_form.ACTION_plan', { ACTION: action })}
</FabButton>
</section>
{categories?.length > 0 && <FormSelect options={categories}
formState={formState}
control={control}
id="plan_category_id"
tooltip={t('app.admin.plan_form.category_help')}
label={t('app.admin.plan_form.category')} />}
{action === 'update' && <FabAlert level="warning">
{t('app.admin.plan_form.edit_amount_info')}
</FabAlert>}
<FormInput register={register}
formState={formState}
id="ui_weight"
type="number"
label={t('app.admin.plan_form.visual_prominence')}
tooltip={t('app.admin.plan_form.visual_prominence_help')} />
<AdvancedAccountingForm register={register} onError={onError} />
{action === 'update' && <PlanPricingForm formState={formState}
control={control}
onError={onError}
setValue={setValue}
register={register} />}
</div>
);
return (
<div className="plan-form">
<header>
<h2>{t('app.admin.plan_form.ACTION_title', { ACTION: action })}</h2>
<div className="grpBtn">
<FabButton type="submit" onClick={handleSubmit(onSubmit)} className="fab-button is-main">
{t('app.admin.plan_form.save')}
</FabButton>
</div>
</header>
<form onSubmit={handleSubmit(onSubmit)}>
<FabTabs tabs={[
{
id: 'settings',
title: t('app.admin.plan_form.tab_settings'),
content: renderSettingsTab()
},
{
id: 'usageLimits',
title: t('app.admin.plan_form.tab_usage_limits'),
content: <pre>plop</pre>
}
]} />
</form>
<PartnerModal isOpen={isOpenPartnerModal}
toggleModal={tooglePartnerModal}
onError={onError}

View File

@ -12,16 +12,20 @@
text-align: center;
color: var(--main);
border-bottom: 1px solid var(--gray-soft-dark);
border-radius: var(--border-radius-sm) var(--border-radius-sm) 0 0;
&:hover {
background-color: var(--gray-soft-light);
cursor: pointer;
}
&.react-tabs__tab--selected {
color: var(--gray-hard-dark);
border: 1px solid var(--gray-soft-dark);
border-bottom: none;
border-radius: var(--border-radius-sm) var(--border-radius-sm) 0 0;
}
&:hover {
cursor: pointer;
&:hover {
background-color: var(--gray-soft-lightest);
cursor: default;
}
}
}
}

View File

@ -1,6 +1,6 @@
.fab-text-editor {
position: relative;
margin-bottom: 1.6rem;
//margin-bottom: 1.6rem;
padding-bottom: 1.6rem;
background-color: var(--gray-soft-lightest);
border: 1px solid var(--gray-soft-dark);

View File

@ -25,7 +25,7 @@
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 2.4rem;
gap: 1.6rem 2.4rem;
.add-price {
max-width: fit-content;
@ -37,6 +37,8 @@
align-items: flex-end;
gap: 0 2.4rem;
.form-item { margin: 0; }
.remove-price {
align-items: center;
display: flex;
@ -61,8 +63,7 @@
flex-direction: column;
@media (min-width: 640px) {flex-direction: row; }
.form-item:first-child {
margin-right: 2.4rem;
}
.form-item { margin: 0; }
.form-item:first-child { margin-right: 2.4rem; }
}
}

View File

@ -1,25 +1,64 @@
.plan-form {
.plan-sheet {
margin-top: 4rem;
max-width: 1260px;
margin: 2.4rem auto 0;
padding: 0 3rem 6rem;
display: flex;
flex-direction: column;
& > header {
padding-bottom: 0;
@include header($sticky: true);
gap: 2.4rem;
}
.duration {
display: flex;
flex-direction: row;
.form-item:first-child {
margin-right: 32px;
}
}
.partner {
&-content {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 3.2rem;
.fab-alert {
width: 100%;
section { @include layout-settings; }
.grp {
display: flex;
flex-direction: column;
@media (min-width: 640px) {flex-direction: row; }
.form-item { margin: 0; }
.form-item:first-child { margin-right: 2.4rem; }
}
.partner {
display: flex;
flex-direction: column-reverse;
align-items: flex-end;
gap: 0 2.4rem;
@media (min-width: 640px) {
flex-direction: row;
button { margin-bottom: 1.6rem; }
}
}
}
.submit-btn {
float: right;
}
//.plan-sheet {
// margin-top: 4rem;
//}
//.duration {
// display: flex;
// flex-direction: row;
// .form-item:first-child {
// margin-right: 32px;
// }
//}
//.partner {
// display: flex;
// flex-direction: column;
// align-items: flex-end;
// .fab-alert {
// width: 100%;
// }
//}
//.submit-btn {
// float: right;
//}
}

View File

@ -29,10 +29,14 @@
}
& > .content {
display: flex;
flex-direction: column;
padding: 1.6rem;
background-color: var(--gray-soft-light);
border: 1px solid var(--gray-soft-dark);
border-radius: var(--border-radius);
& > * { margin-bottom: 0; }
& > *:not(:last-child) { margin-bottom: 3.2rem; }
}
@media (min-width: 1024px) {

View File

@ -10,24 +10,7 @@
<h1>{{ 'app.admin.plans.edit.subscription_plan' | translate }} {{ suscriptionPlan.base_name }}</h1>
</section>
</div>
<div class="col-md-3">
<section class="heading-actions wrapper">
<a class="btn btn-lg btn-block btn-default m-t-xs" ui-sref="app.admin.pricing" translate>{{ 'app.shared.buttons.cancel' }}</a>
</section>
</div>
</div>
</section>
<div class="row no-gutter">
<div class=" col-sm-12 col-md-9 b-r nopadding">
<div class="panel panel-default bg-light m-lg">
<div class="panel-body m-r">
<plan-form action="'update'" plan="suscriptionPlan" on-error="onError" on-success="onSuccess"></plan-form>
</div>
</div>
</div>
</div>
<plan-form action="'update'" plan="suscriptionPlan" on-error="onError" on-success="onSuccess"></plan-form>

View File

@ -14,14 +14,4 @@
</div>
</section>
<div class="row no-gutter">
<div class=" col-sm-12 col-md-9 b-r nopadding">
<div class="panel panel-default bg-light m-lg">
<div class="panel-body m-r">
<plan-form action="'create'" on-error="onError" on-success="onSuccess"></plan-form>
</div>
</div>
</div>
</div>
<plan-form action="'create'" on-error="onError" on-success="onSuccess"></plan-form>

View File

@ -152,7 +152,13 @@ en:
every_month: "Every month"
every_year: "Every year"
plan_form:
general_information: "General information"
ACTION_title: "{ACTION, select, create{New} other{Update the}} plan"
tab_settings: "Settings"
tab_usage_limits: "Usage limits"
description: "Description"
general_settings: "General settings"
general_settings_info: "Determine to which group this subscription is dedicated. Also set its price and duration in periods."
activation_and_payment: "Subscription activation and payment"
name: "Name"
name_max_length: "Name length must be less than 24 characters."
group: "Group"
@ -185,7 +191,7 @@ en:
partner_plan: "Partner plan"
partner_plan_help: "You can sell subscriptions in partnership with another organization. By doing so, the other organization will be notified when a member subscribes to this subscription plan."
partner_created: "The partner was successfully created"
ACTION_plan: "{ACTION, select, create{Create} other{Update}} the plan"
save: "Save"
create_success: "Plan(s) successfully created. Don't forget to redefine prices."
update_success: "The plan was updated successfully"
partner_modal: