using System.Collections.ObjectModel;
using System.Windows;
using SheetMe.Data.Stores;
using SheetMe.Designer.Services;
namespace SheetMe.Designer.Views;
///
/// 서식별 상용구 관리 대화상자 — E_SHTWRDMST 1단계 문구 추가/수정/삭제/순서.
/// 레거시 런타임 상용구 팝업(MRecordWord)이 그대로 읽어가는 데이터를 관리한다.
///
public partial class RecordWordDialogView : Window
{
#region Member Fields
private readonly RecordWordStore store;
private readonly string shtCod;
private readonly string auditUid;
private readonly bool canWrite;
private readonly ObservableCollection words = new();
#endregion
#region Constructors
/// 감사 컬럼(ShtUpdUid/ShtFstUid)에 기록할 HIS 사용자 코드
/// DB 쓰기 가능 여부 — 미인증/게이트 차단이면 읽기 전용으로 연다
public RecordWordDialogView(RecordWordStore store, string shtCod, string sheetTitle, string auditUid, bool canWrite)
{
this.store = store;
this.shtCod = shtCod;
this.auditUid = auditUid;
this.canWrite = canWrite;
InitializeComponent();
HeaderText.Text = $"[{shtCod}] {sheetTitle} — 작성 화면의 상용구 팝업에 표시되는 문구입니다. " +
"(텍스트박스의 '상용구 사용'이 켜져 있어야 합니다)" +
(canWrite ? string.Empty : "\n※ HIS 사용자가 확인되지 않아 읽기 전용입니다.");
WordList.ItemsSource = words;
Loaded += (_, _) => Reload();
NewWordBox.Loaded += (_, _) => NewWordBox.Focus();
}
#endregion
#region Methods - 가드
/// 쓰기 전 확인 — 미인증이면 안내 후 차단(감사 컬럼에 남길 주체가 없다)
private bool EnsureWritable()
{
if (canWrite)
{
return true;
}
DialogService.Notify(DialogKind.Warning, "상용구 관리",
"HIS 사용자가 확인되지 않아 상용구를 변경할 수 없습니다.",
"기록지정보 화면에서 서식생성기를 실행해 주세요.", this);
return false;
}
#endregion
#region Methods
private void Reload()
{
try
{
words.Clear();
foreach (var word in store.List(shtCod))
{
words.Add(word);
}
}
catch (Exception ex)
{
DialogService.Notify(DialogKind.Error, "오류", "상용구 조회 중 오류가 발생했습니다.", ex.Message, this);
}
}
private void OnAdd(object sender, RoutedEventArgs e)
{
var value = NewWordBox.Text.Trim();
if (value.Length == 0 || !EnsureWritable())
{
return;
}
try
{
store.Add(shtCod, value, auditUid);
NewWordBox.Clear();
NewWordBox.Focus();
Reload();
WordList.SelectedIndex = words.Count - 1;
}
catch (Exception ex)
{
DialogService.Notify(DialogKind.Error, "오류", "추가 중 오류가 발생했습니다.", ex.Message, this);
}
}
private void OnEdit(object sender, RoutedEventArgs e)
{
if (WordList.SelectedItem is not RecordWordInfo selected || !EnsureWritable())
{
return;
}
// QueryEditorWindow 재사용(큰 다중행 편집 영역) — SQL 이 아니므로 치환 변수 패널은 숨긴다
var editor = new QueryEditorWindow("상용구 수정", selected.Value, showVariables: false) { Owner = this };
if (editor.ShowDialog() != true)
{
return;
}
var newValue = editor.QueryText.Trim();
if (newValue.Length == 0 || newValue == selected.Value)
{
return;
}
try
{
store.Update(selected.Key, newValue, auditUid);
Reload();
}
catch (Exception ex)
{
DialogService.Notify(DialogKind.Error, "오류", "수정 중 오류가 발생했습니다.", ex.Message, this);
}
}
private void OnRemove(object sender, RoutedEventArgs e)
{
if (WordList.SelectedItem is not RecordWordInfo selected || !EnsureWritable())
{
return;
}
if (!DialogService.Confirm("상용구 삭제", "삭제할까요?", Truncate(selected.Value),
yes: "삭제", no: "취소", destructive: true, owner: this))
{
return;
}
try
{
store.Remove(selected.Key, auditUid);
Reload();
}
catch (Exception ex)
{
DialogService.Notify(DialogKind.Error, "오류", "삭제 중 오류가 발생했습니다.", ex.Message, this);
}
}
private void OnMoveUp(object sender, RoutedEventArgs e) => Move(-1);
private void OnMoveDown(object sender, RoutedEventArgs e) => Move(+1);
private void Move(int delta)
{
var index = WordList.SelectedIndex;
var target = index + delta;
if (index < 0 || target < 0 || target >= words.Count || !EnsureWritable())
{
return;
}
try
{
words.Move(index, target);
store.Reorder(words.Select(w => w.Key).ToList(), auditUid);
WordList.SelectedIndex = target;
}
catch (Exception ex)
{
DialogService.Notify(DialogKind.Error, "오류", "순서 변경 중 오류가 발생했습니다.", ex.Message, this);
Reload();
}
}
private static string Truncate(string value)
=> value.Length > 80 ? value[..80] + "…" : value;
#endregion
}