@using System @using System.Collections.Generic @using System.Linq @using RolemasterDb.App.Domain @using RolemasterDb.App.Features
@if (Model is not null) {

Edit Result Card

@Model.TableName · Roll band @Model.RollBand · Severity @Model.ColumnLabel @if (!string.IsNullOrWhiteSpace(Model.GroupLabel)) { · Variant @Model.GroupLabel }

} else {

Edit Result Card

}
@if (IsLoading) {

Loading editor...

} else if (!string.IsNullOrWhiteSpace(LoadErrorMessage)) {

@LoadErrorMessage

} else if (Model is not null) {
@if (!string.IsNullOrWhiteSpace(SaveErrorMessage)) {

@SaveErrorMessage

}

Result Preview

This is the card the table browser will show.

Severity: @Model.ColumnLabel Roll band: @Model.RollBand @if (!string.IsNullOrWhiteSpace(Model.GroupLabel)) { Variant: @Model.GroupLabel }

Raw Text

Update the source text, then adjust the visible card fields below.

Base Effects

These chips appear on the main result.

@if (Model.Effects.Count == 0) {

No base effects on this result yet.

} else {
@for (var index = 0; index < Model.Effects.Count; index++) { var effect = Model.Effects[index]; var effectIndex = index;
@GetEffectLabel(effect)
}
@for (var index = 0; index < Model.Effects.Count; index++) { var effect = Model.Effects[index];
@GetEffectLabel(effect)
@EffectFields(effect)
} }

Conditions

Use condition cards for alternate outcomes.

@if (Model.Branches.Count == 0) {

No alternate condition cards on this result yet.

} else { @for (var index = 0; index < Model.Branches.Count; index++) { var branch = Model.Branches[index];
@GetBranchTitle(branch, index)

Shown when this condition applies.

Condition Effects

These chips only appear when the condition is met.

@if (branch.Effects.Count == 0) {

No effects on this condition card yet.

} else {
@for (var effectIndex = 0; effectIndex < branch.Effects.Count; effectIndex++) { var effect = branch.Effects[effectIndex]; var localEffectIndex = effectIndex;
@GetEffectLabel(effect)
}
@for (var effectIndex = 0; effectIndex < branch.Effects.Count; effectIndex++) { var effect = branch.Effects[effectIndex];
@GetEffectLabel(effect)
@EffectFields(effect)
} }
} }
}
@code { [Parameter, EditorRequired] public CriticalCellEditorModel? Model { get; set; } [Parameter] public bool IsLoading { get; set; } [Parameter] public bool IsSaving { get; set; } [Parameter] public string? LoadErrorMessage { get; set; } [Parameter] public string? SaveErrorMessage { get; set; } [Parameter, EditorRequired] public EventCallback OnClose { get; set; } [Parameter, EditorRequired] public EventCallback OnSave { get; set; } private async Task HandleBackdropClicked() { await OnClose.InvokeAsync(); } private async Task HandleSubmitAsync(EditContext _) { await OnSave.InvokeAsync(); } private void AddBaseEffect() { Model?.Effects.Add(CreateDefaultEffectModel()); } private void RemoveBaseEffect(int index) { if (Model is null || index < 0 || index >= Model.Effects.Count) { return; } Model.Effects.RemoveAt(index); } private void AddBranch() { if (Model is null) { return; } Model.Branches.Add(new CriticalBranchEditorModel { ConditionText = $"Condition {Model.Branches.Count + 1}", SortOrder = Model.Branches.Count + 1 }); } private void RemoveBranch(int index) { if (Model is null || index < 0 || index >= Model.Branches.Count) { return; } Model.Branches.RemoveAt(index); } private static void AddBranchEffect(CriticalBranchEditorModel branch) { branch.Effects.Add(CreateDefaultEffectModel()); } private static void RemoveBranchEffect(CriticalBranchEditorModel branch, int index) { if (index < 0 || index >= branch.Effects.Count) { return; } branch.Effects.RemoveAt(index); } private static CriticalEffectEditorModel CreateDefaultEffectModel() => new() { EffectCode = CriticalEffectCodes.DirectHits, SourceType = "symbol" }; private static string GetBranchTitle(CriticalBranchEditorModel branch, int index) => string.IsNullOrWhiteSpace(branch.ConditionText) ? $"Condition {index + 1}" : branch.ConditionText; private static string GetEffectLabel(CriticalEffectEditorModel effect) { if (AffixDisplayMap.TryGet(effect.EffectCode, out var info)) { return info.Label; } return string.IsNullOrWhiteSpace(effect.EffectCode) ? "Custom Effect" : effect.EffectCode; } private static IEnumerable> GetEffectOptions(string? currentCode) { if (!string.IsNullOrWhiteSpace(currentCode) && !AffixDisplayMap.Entries.ContainsKey(currentCode)) { yield return new KeyValuePair(currentCode, currentCode); } foreach (var entry in AffixDisplayMap.Entries.OrderBy(item => item.Value.Label)) { yield return new KeyValuePair(entry.Key, entry.Value.Label); } } private static void HandleEffectCodeChanged(CriticalEffectEditorModel effect, string? newCode) { var normalizedCode = newCode?.Trim() ?? string.Empty; if (string.Equals(effect.EffectCode, normalizedCode, StringComparison.Ordinal)) { return; } effect.EffectCode = normalizedCode; effect.Target = null; effect.ValueInteger = null; effect.ValueDecimal = null; effect.ValueExpression = null; effect.DurationRounds = null; effect.PerRound = null; effect.Modifier = null; effect.BodyPart = null; effect.IsPermanent = false; effect.SourceText = null; effect.SourceType = AffixDisplayMap.TryGet(effect.EffectCode, out _) ? "symbol" : "manual"; } private static IReadOnlyList BuildPreviewEffects(IEnumerable effects) => effects.Select(CreatePreviewEffect).ToList(); private static IReadOnlyList BuildSinglePreviewEffect(CriticalEffectEditorModel effect) => [CreatePreviewEffect(effect)]; private static IReadOnlyList BuildPreviewBranches(IEnumerable branches) => branches .OrderBy(branch => branch.SortOrder) .Select(branch => new CriticalBranchLookupResponse( branch.BranchKind, branch.ConditionKey, branch.ConditionText, branch.DescriptionText, branch.RawAffixText, BuildPreviewEffects(branch.Effects), branch.RawText, branch.SortOrder)) .ToList(); private static CriticalEffectLookupResponse CreatePreviewEffect(CriticalEffectEditorModel effect) => new( effect.EffectCode, effect.Target, effect.ValueInteger, effect.ValueExpression, effect.DurationRounds, effect.PerRound, effect.Modifier, effect.BodyPart, effect.IsPermanent, effect.SourceType, effect.SourceText); } @functions { private RenderFragment EffectFields(CriticalEffectEditorModel effect) => @
@switch (effect.EffectCode) { case CriticalEffectCodes.DirectHits:
break; case CriticalEffectCodes.StunnedRounds: case CriticalEffectCodes.MustParryRounds: case CriticalEffectCodes.NoParryRounds:
break; case CriticalEffectCodes.BleedPerRound:
break; case CriticalEffectCodes.FoePenalty: case CriticalEffectCodes.AttackerBonusNextRound:
break; case CriticalEffectCodes.PowerPointModifier:
break; default:
break; } @if (!string.IsNullOrWhiteSpace(effect.BodyPart)) {
} @if (!string.IsNullOrWhiteSpace(effect.Target)) {
}
; }