Files
jongryangje/app/Views/admin/feedback/all.php
taekyoungc 8339f69303 feat: 의견 상세/전체보기의 화면 URL을 클릭 가능한 링크로
fb_page_url을 embed=1 파라미터 제거 후 전체 절대 URL로 변환해
새 탭(target=_blank)으로 바로 열리게 한다. 나머지 쿼리는 보존.
2026-07-06 19:29:27 +09:00

118 lines
6.0 KiB
PHP

<?php
declare(strict_types=1);
/**
* @var list<object> $list
* @var array<int, list<object>> $filesByFb
* @var string $status
*/
use App\Models\FeedbackModel;
$list = $list ?? [];
$filesByFb = $filesByFb ?? [];
$status = (string) ($status ?? '');
$badge = static function (string $s): string {
$map = [
'new' => 'bg-blue-50 text-blue-700',
'in_progress' => 'bg-amber-50 text-amber-700',
'answered' => 'bg-gray-100 text-gray-500',
'done' => 'bg-emerald-50 text-emerald-700',
'hold' => 'bg-gray-100 text-gray-500',
];
$c = $map[$s] ?? 'bg-gray-100 text-gray-600';
return '<span class="inline-block px-2 py-0.5 rounded-full text-[11px] font-medium ' . $c . '">' . esc(FeedbackModel::statusLabel($s)) . '</span>';
};
?>
<section class="border-b border-gray-300 p-2 shrink-0 bg-control-panel flex flex-wrap items-center justify-between gap-2">
<span class="text-sm font-bold text-gray-700">사용자 의견 · 전체보기 (<?= count($list) ?>건)</span>
<div class="flex items-center gap-2">
<form method="get" class="flex items-center gap-2 text-sm">
<select name="status" class="border border-gray-300 rounded px-3 py-1 text-sm w-40 min-w-[10rem]" onchange="this.form.submit()">
<option value="">전체 상태</option>
<?php foreach (FeedbackModel::STATUSES as $s): ?>
<option value="<?= esc($s, 'attr') ?>" <?= $status === $s ? 'selected' : '' ?>><?= esc(FeedbackModel::statusLabel($s)) ?></option>
<?php endforeach; ?>
</select>
</form>
<a href="<?= site_url('admin/feedback') ?>" class="text-sm text-gray-600 hover:underline whitespace-nowrap">목록형으로 보기</a>
</div>
</section>
<?php if (empty($list)): ?>
<div class="border border-gray-300 rounded-lg p-10 text-center text-gray-400 mt-2">접수된 의견이 없습니다.</div>
<?php else: ?>
<!-- 빠른 이동 — 클릭하면 아래 해당 의견으로 스크롤 -->
<div class="border border-gray-300 rounded-lg bg-white p-2 mt-2 sticky top-0 z-10 shadow-sm">
<div class="flex flex-wrap gap-1.5 max-h-24 overflow-auto">
<?php foreach ($list as $row): ?>
<a href="#fb-<?= (int) $row->fb_idx ?>" class="inline-flex items-center gap-1 border border-gray-200 rounded-full px-2 py-0.5 text-[11px] text-gray-600 hover:bg-blue-50 hover:border-blue-200 whitespace-nowrap">
#<?= (int) $row->fb_idx ?> <?= $badge((string) ($row->fb_status ?? 'new')) ?>
</a>
<?php endforeach; ?>
</div>
</div>
<div class="space-y-3 mt-3">
<?php foreach ($list as $row): $fid = (int) $row->fb_idx; $files = $filesByFb[$fid] ?? []; ?>
<section id="fb-<?= $fid ?>" class="border border-gray-300 rounded-lg overflow-hidden bg-white scroll-mt-20">
<div class="px-3 py-2 border-b bg-gray-50 flex flex-wrap items-center justify-between gap-2">
<div class="flex items-center gap-2 text-sm">
<span class="font-bold text-gray-800">#<?= $fid ?></span>
<?= $badge((string) ($row->fb_status ?? 'new')) ?>
<span class="text-gray-500 text-[12px]"><?= esc((string) ($row->fb_regdate ?? '')) ?></span>
<span class="text-gray-400 text-[12px]">·</span>
<span class="text-gray-600 text-[12px]"><?= esc((string) ($row->fb_mb_name ?? '')) ?></span>
</div>
<?php
$fbUrlRaw = (string) ($row->fb_page_url ?? '');
$fbUrlOpen = $fbUrlRaw;
if ($fbUrlOpen !== '' && ! preg_match('#^https?://#i', $fbUrlOpen)) {
$fbUrlOpen = (string) preg_replace('/([?&])embed=1(?=&|$)/', '$1', $fbUrlOpen);
$fbUrlOpen = rtrim($fbUrlOpen, '?&');
$fbUrlOpen = base_url(ltrim($fbUrlOpen, '/'));
}
?>
<div class="text-[12px] text-gray-500">
<?= esc((string) ($row->fb_page_title ?: '-')) ?>
<?php if ($fbUrlRaw !== ''): ?>
<span class="text-gray-400"> · </span><a href="<?= esc($fbUrlOpen, 'attr') ?>" target="_blank" rel="noopener" class="text-blue-600 hover:underline break-all"><?= esc($fbUrlRaw) ?></a>
<?php endif; ?>
</div>
</div>
<div class="p-3 grid grid-cols-1 lg:grid-cols-[1fr_20rem] gap-3">
<div>
<p class="whitespace-pre-wrap text-sm text-gray-800"><?= esc((string) $row->fb_content) ?></p>
<?php if (! empty($files)): ?>
<div class="flex flex-col gap-3 mt-3">
<?php foreach ($files as $f): ?>
<a href="<?= site_url('admin/feedback/file/' . (int) $f->ff_idx) ?>" target="_blank" rel="noopener" title="새 창에서 원본 크기로 보기">
<img src="<?= site_url('admin/feedback/file/' . (int) $f->ff_idx) ?>" alt="첨부 이미지"
style="max-width:100%;width:640px;height:auto;border:1px solid #e5e7eb;border-radius:6px;"/>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<form action="<?= site_url('admin/feedback/' . $fid . '/status') ?>" method="post" class="space-y-2 border-t lg:border-t-0 lg:border-l border-gray-200 pt-3 lg:pt-0 lg:pl-3">
<?= csrf_field() ?>
<input type="hidden" name="return_to" value="all"/>
<div class="flex items-center gap-2">
<select name="fb_status" class="border border-gray-300 rounded px-2 py-1 text-sm flex-1">
<?php foreach (FeedbackModel::STATUSES as $s): ?>
<option value="<?= esc($s, 'attr') ?>" <?= (string) $row->fb_status === $s ? 'selected' : '' ?>><?= esc(FeedbackModel::statusLabel($s)) ?></option>
<?php endforeach; ?>
</select>
<a href="<?= site_url('admin/feedback/' . $fid) ?>" class="text-[12px] text-gray-500 hover:underline whitespace-nowrap">상세</a>
</div>
<textarea name="fb_admin_memo" rows="3" placeholder="처리 메모" class="w-full border border-gray-300 rounded px-2 py-1.5 text-[12px]" maxlength="2000"><?= esc((string) ($row->fb_admin_memo ?? '')) ?></textarea>
<button type="submit" class="bg-btn-search text-white px-3 py-1 rounded-sm text-[12px] w-full">저장</button>
</form>
</div>
</section>
<?php endforeach; ?>
</div>
<?php endif; ?>