mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-07 01:54:16 +01:00
(feat) save new limitations
This commit is contained in:
parent
dad3babbe4
commit
622a14909a
@ -85,7 +85,7 @@ class API::PlansController < API::ApiController
|
|||||||
plan_file_attributes: %i[id attachment _destroy],
|
plan_file_attributes: %i[id attachment _destroy],
|
||||||
prices_attributes: %i[id amount],
|
prices_attributes: %i[id amount],
|
||||||
advanced_accounting_attributes: %i[code analytical_section],
|
advanced_accounting_attributes: %i[code analytical_section],
|
||||||
plan_limitations_attributes: %i[limitable_id limitable_type limit])
|
plan_limitations_attributes: %i[id limitable_id limitable_type limit])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -6,7 +6,7 @@ import { FabButton } from '../base/fab-button';
|
|||||||
import { PencilSimple, Trash } from 'phosphor-react';
|
import { PencilSimple, Trash } from 'phosphor-react';
|
||||||
import { PlanLimitModal } from './plan-limit-modal';
|
import { PlanLimitModal } from './plan-limit-modal';
|
||||||
import { Plan, PlanLimitation } from '../../models/plan';
|
import { Plan, PlanLimitation } from '../../models/plan';
|
||||||
import { useFieldArray, UseFormRegister } from 'react-hook-form';
|
import { useFieldArray, UseFormRegister, useWatch } from 'react-hook-form';
|
||||||
import { Machine } from '../../models/machine';
|
import { Machine } from '../../models/machine';
|
||||||
import { MachineCategory } from '../../models/machine-category';
|
import { MachineCategory } from '../../models/machine-category';
|
||||||
import MachineAPI from '../../api/machine';
|
import MachineAPI from '../../api/machine';
|
||||||
@ -26,6 +26,7 @@ interface PlanLimitFormProps<TContext extends object> {
|
|||||||
export const PlanLimitForm = <TContext extends object> ({ register, control, formState, onError }: PlanLimitFormProps<TContext>) => {
|
export const PlanLimitForm = <TContext extends object> ({ register, control, formState, onError }: PlanLimitFormProps<TContext>) => {
|
||||||
const { t } = useTranslation('admin');
|
const { t } = useTranslation('admin');
|
||||||
const { fields, append, remove } = useFieldArray<Plan, 'plan_limitations_attributes'>({ control, name: 'plan_limitations_attributes' });
|
const { fields, append, remove } = useFieldArray<Plan, 'plan_limitations_attributes'>({ control, name: 'plan_limitations_attributes' });
|
||||||
|
const limiting = useWatch<Plan>({ control, name: 'limiting' });
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||||
const [machines, setMachines] = useState<Array<Machine>>([]);
|
const [machines, setMachines] = useState<Array<Machine>>([]);
|
||||||
@ -90,7 +91,7 @@ export const PlanLimitForm = <TContext extends object> ({ register, control, for
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div className="plan-limit-grp">
|
{limiting && <div className="plan-limit-grp">
|
||||||
<header>
|
<header>
|
||||||
<p>{t('app.admin.plan_limit_form.all_limitations')}</p>
|
<p>{t('app.admin.plan_limit_form.all_limitations')}</p>
|
||||||
<div className="grpBtn">
|
<div className="grpBtn">
|
||||||
@ -100,23 +101,24 @@ export const PlanLimitForm = <TContext extends object> ({ register, control, for
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
{fields.filter(f => f.limitable_type === 'MachineCategory').length > 0 &&
|
||||||
<div className='plan-limit-list'>
|
<div className='plan-limit-list'>
|
||||||
<p className="title">{t('app.admin.plan_limit_form.by_categories')}</p>
|
<p className="title">{t('app.admin.plan_limit_form.by_categories')}</p>
|
||||||
<div className="plan-limit-item">
|
{fields.filter(f => f.limitable_type === 'MachineCategory' && !f.modified).map(limitation => (
|
||||||
|
<div className="plan-limit-item" key={limitation.id}>
|
||||||
<div className="grp">
|
<div className="grp">
|
||||||
<div>
|
<div>
|
||||||
<span>{t('app.admin.plan_limit_form.category')}</span>
|
<span>{t('app.admin.plan_limit_form.category')}</span>
|
||||||
<p>Plop</p>
|
<p>{categories.find(c => c.id === limitation.limitable_id)?.name}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>{t('app.admin.plan_limit_form.max_hours_per_day')}</span>
|
<span>{t('app.admin.plan_limit_form.max_hours_per_day')}</span>
|
||||||
<p>5</p>
|
<p>{limitation.limit}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='actions'>
|
<div className='actions'>
|
||||||
<div className='grpBtn'>
|
<div className='grpBtn'>
|
||||||
{/* TODO, use <EditDestroyButtons> */}
|
|
||||||
<FabButton className='edit-btn'>
|
<FabButton className='edit-btn'>
|
||||||
<PencilSimple size={20} weight="fill" />
|
<PencilSimple size={20} weight="fill" />
|
||||||
</FabButton>
|
</FabButton>
|
||||||
@ -126,29 +128,32 @@ export const PlanLimitForm = <TContext extends object> ({ register, control, for
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
|
|
||||||
<FormUnsavedList fields={fields}
|
<FormUnsavedList fields={fields}
|
||||||
remove={remove}
|
remove={remove}
|
||||||
register={register}
|
register={register}
|
||||||
title={t('app.admin.plan_limit_form.ongoing_limitations')}
|
title={t('app.admin.plan_limit_form.ongoing_limitations')}
|
||||||
shouldRenderField={(limit: PlanLimitation) => limit.limitable_type === 'MachineCategory'}
|
shouldRenderField={(limit: PlanLimitation) => limit.limitable_type === 'MachineCategory' && limit.modified}
|
||||||
formAttributeName="plan_limitations_attributes"
|
formAttributeName="plan_limitations_attributes"
|
||||||
formAttributes={['limitable_id', 'limit']}
|
formAttributes={['id', 'limitable_type', 'limitable_id', 'limit']}
|
||||||
renderField={renderOngoingLimit}
|
renderField={renderOngoingLimit}
|
||||||
cancelLabel={t('app.admin.plan_limit_form.cancel')} />
|
cancelLabel={t('app.admin.plan_limit_form.cancel')} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{fields.filter(f => f.limitable_type === 'Machine').length > 0 &&
|
||||||
<div className='plan-limit-list'>
|
<div className='plan-limit-list'>
|
||||||
<p className="title">{t('app.admin.plan_limit_form.by_machine')}</p>
|
<p className="title">{t('app.admin.plan_limit_form.by_machine')}</p>
|
||||||
<div className="plan-limit-item">
|
{fields.filter(f => f.limitable_type === 'Machine' && !f.modified).map(limitation => (
|
||||||
|
<div className="plan-limit-item" key={limitation.id}>
|
||||||
<div className="grp">
|
<div className="grp">
|
||||||
<div>
|
<div>
|
||||||
<span>{t('app.admin.plan_limit_form.machine')}</span>
|
<span>{t('app.admin.plan_limit_form.machine')}</span>
|
||||||
<p>Pouet</p>
|
<p>{machines.find(m => m.id === limitation.limitable_id)?.name}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span>{t('app.admin.plan_limit_form.max_hours_per_day')}</span>
|
<span>{t('app.admin.plan_limit_form.max_hours_per_day')}</span>
|
||||||
<p>5</p>
|
<p>{limitation.limit}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -163,19 +168,19 @@ export const PlanLimitForm = <TContext extends object> ({ register, control, for
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
))}
|
||||||
</div>
|
|
||||||
|
|
||||||
<FormUnsavedList fields={fields}
|
<FormUnsavedList fields={fields}
|
||||||
remove={remove}
|
remove={remove}
|
||||||
register={register}
|
register={register}
|
||||||
title={t('app.admin.plan_limit_form.ongoing_limit')}
|
title={t('app.admin.plan_limit_form.ongoing_limitations')}
|
||||||
shouldRenderField={(limit: PlanLimitation) => limit.limitable_type === 'Machine'}
|
shouldRenderField={(limit: PlanLimitation) => limit.limitable_type === 'Machine' && limit.modified}
|
||||||
formAttributeName="plan_limitations_attributes"
|
formAttributeName="plan_limitations_attributes"
|
||||||
formAttributes={['limitable_id', 'limit']}
|
formAttributes={['id', 'limitable_type', 'limitable_id', 'limit']}
|
||||||
renderField={renderOngoingLimit}
|
renderField={renderOngoingLimit}
|
||||||
saveReminderLabel={t('app.admin.plan_limit_form.save_reminder')}
|
|
||||||
cancelLabel={t('app.admin.plan_limit_form.cancel')} />
|
cancelLabel={t('app.admin.plan_limit_form.cancel')} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>}
|
||||||
|
|
||||||
<PlanLimitModal isOpen={isOpen}
|
<PlanLimitModal isOpen={isOpen}
|
||||||
machines={machines}
|
machines={machines}
|
||||||
|
@ -47,7 +47,7 @@ export const PlanLimitModal: React.FC<PlanLimitModalProps> = ({ isOpen, toggleMo
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
return handleSubmit((data: PlanLimitation) => {
|
return handleSubmit((data: PlanLimitation) => {
|
||||||
onSuccess(data);
|
onSuccess({ ...data, modified: true });
|
||||||
toggleModal();
|
toggleModal();
|
||||||
})(event);
|
})(event);
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,8 @@ export interface PlanLimitation {
|
|||||||
id?: number,
|
id?: number,
|
||||||
limitable_id: number,
|
limitable_id: number,
|
||||||
limitable_type: LimitableType,
|
limitable_type: LimitableType,
|
||||||
limit: number
|
limit: number,
|
||||||
|
modified?: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Plan {
|
export interface Plan {
|
||||||
@ -42,6 +43,7 @@ export interface Plan {
|
|||||||
plan_file_url?: string,
|
plan_file_url?: string,
|
||||||
partner_id?: number,
|
partner_id?: number,
|
||||||
partnership?: boolean,
|
partnership?: boolean,
|
||||||
|
limiting?: boolean,
|
||||||
partners?: Array<Partner>,
|
partners?: Array<Partner>,
|
||||||
advanced_accounting_attributes?: AdvancedAccounting,
|
advanced_accounting_attributes?: AdvancedAccounting,
|
||||||
plan_limitations_attributes?: Array<PlanLimitation>
|
plan_limitations_attributes?: Array<PlanLimitation>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
.title { @include text-base(500); }
|
& > .title { @include text-base(500); }
|
||||||
.plan-limit-item {
|
.plan-limit-item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-bottom: 2.4rem;
|
margin-bottom: 2.4rem;
|
||||||
|
@ -8,5 +8,6 @@ class PlanLimitation < ApplicationRecord
|
|||||||
belongs_to :machine, foreign_type: 'Machine', foreign_key: 'limitable_id', inverse_of: :plan_limitations
|
belongs_to :machine, foreign_type: 'Machine', foreign_key: 'limitable_id', inverse_of: :plan_limitations
|
||||||
belongs_to :machine_category, foreign_type: 'MachineCategory', foreign_key: 'limitable_id', inverse_of: :plan_limitations
|
belongs_to :machine_category, foreign_type: 'MachineCategory', foreign_key: 'limitable_id', inverse_of: :plan_limitations
|
||||||
|
|
||||||
validates :limitable_id, :limitable_type, :limit, presence: true
|
validates :limitable_id, :limitable_type, :limit, :plan_id, presence: true
|
||||||
|
validates :plan_id, :limitable_id, :limitable_type, uniqueness: true
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
json.extract! plan, :id, :base_name, :name, :interval, :interval_count, :group_id, :training_credit_nb, :is_rolling, :description, :type,
|
json.extract! plan, :id, :base_name, :name, :interval, :interval_count, :group_id, :training_credit_nb, :is_rolling, :description, :type,
|
||||||
:ui_weight, :disabled, :monthly_payment, :plan_category_id
|
:ui_weight, :disabled, :monthly_payment, :plan_category_id, :limiting
|
||||||
json.amount plan.amount / 100.00
|
json.amount plan.amount / 100.00
|
||||||
json.prices_attributes plan.prices, partial: 'api/prices/price', as: :price
|
json.prices_attributes plan.prices, partial: 'api/prices/price', as: :price
|
||||||
if plan.plan_file
|
if plan.plan_file
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
class CreatePlanLimitations < ActiveRecord::Migration[5.2]
|
class CreatePlanLimitations < ActiveRecord::Migration[5.2]
|
||||||
def change
|
def change
|
||||||
create_table :plan_limitations do |t|
|
create_table :plan_limitations do |t|
|
||||||
t.references :plan, foreign_key: true, index: true
|
t.references :plan, foreign_key: true, index: true, null: false
|
||||||
t.references :limitable, polymorphic: true
|
t.references :limitable, polymorphic: true, null: false
|
||||||
t.integer :limit, null: false, default: 0
|
t.integer :limit, null: false, default: 0
|
||||||
|
|
||||||
t.timestamps
|
t.timestamps
|
||||||
end
|
end
|
||||||
|
|
||||||
|
add_index :plan_limitations, %i[plan_id limitable_id limitable_type], unique: true, name: 'index_plan_limitations_on_plan_and_limitable'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -740,13 +740,14 @@ ActiveRecord::Schema.define(version: 2023_03_09_094535) do
|
|||||||
end
|
end
|
||||||
|
|
||||||
create_table "plan_limitations", force: :cascade do |t|
|
create_table "plan_limitations", force: :cascade do |t|
|
||||||
t.bigint "plan_id"
|
t.bigint "plan_id", null: false
|
||||||
t.string "limitable_type"
|
t.string "limitable_type", null: false
|
||||||
t.bigint "limitable_id"
|
t.bigint "limitable_id", null: false
|
||||||
t.integer "limit", default: 0, null: false
|
t.integer "limit", default: 0, null: false
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.index ["limitable_type", "limitable_id"], name: "index_plan_limitations_on_limitable_type_and_limitable_id"
|
t.index ["limitable_type", "limitable_id"], name: "index_plan_limitations_on_limitable_type_and_limitable_id"
|
||||||
|
t.index ["plan_id", "limitable_id", "limitable_type"], name: "index_plan_limitations_on_plan_and_limitable", unique: true
|
||||||
t.index ["plan_id"], name: "index_plan_limitations_on_plan_id"
|
t.index ["plan_id"], name: "index_plan_limitations_on_plan_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user