feat: 문의사항 상세에서 글(본문) 수정 기능
- 의견 내용 패널에 '수정' 토글 → 본문 편집·저장(계정 스코프·2000자 제한) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -258,6 +258,7 @@ $routes->group('admin', ['filter' => 'adminAuth'], static function ($routes): vo
|
|||||||
$routes->get('feedback/file/(:num)', 'Admin\Feedback::file/$1');
|
$routes->get('feedback/file/(:num)', 'Admin\Feedback::file/$1');
|
||||||
$routes->get('feedback/(:num)', 'Admin\Feedback::show/$1');
|
$routes->get('feedback/(:num)', 'Admin\Feedback::show/$1');
|
||||||
$routes->post('feedback/(:num)/status', 'Admin\Feedback::updateStatus/$1');
|
$routes->post('feedback/(:num)/status', 'Admin\Feedback::updateStatus/$1');
|
||||||
|
$routes->post('feedback/(:num)/content', 'Admin\Feedback::updateContent/$1');
|
||||||
$routes->get('/', 'Admin\Dashboard::index');
|
$routes->get('/', 'Admin\Dashboard::index');
|
||||||
$routes->get('users', 'Admin\User::index');
|
$routes->get('users', 'Admin\User::index');
|
||||||
$routes->get('users/create', 'Admin\User::create');
|
$routes->get('users/create', 'Admin\User::create');
|
||||||
|
|||||||
@@ -142,6 +142,30 @@ class Feedback extends BaseController
|
|||||||
return redirect()->to(site_url('admin/feedback/' . $id))->with('success', '처리 상태를 저장했습니다.');
|
return redirect()->to(site_url('admin/feedback/' . $id))->with('success', '처리 상태를 저장했습니다.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 문의 글(본문) 수정 */
|
||||||
|
public function updateContent(int $id): ResponseInterface
|
||||||
|
{
|
||||||
|
$model = model(FeedbackModel::class);
|
||||||
|
$row = $model->find($id);
|
||||||
|
$scope = $this->scopeLgIdx();
|
||||||
|
if ($row === null || ($scope !== null && (int) $row->fb_lg_idx !== $scope)) {
|
||||||
|
return redirect()->to(site_url('admin/feedback'))->with('error', '의견을 찾을 수 없습니다.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = trim((string) $this->request->getPost('fb_content'));
|
||||||
|
if ($content === '') {
|
||||||
|
return redirect()->to(site_url('admin/feedback/' . $id))->with('error', '내용을 입력해 주세요.');
|
||||||
|
}
|
||||||
|
$model->update($id, ['fb_content' => mb_substr($content, 0, 2000)]);
|
||||||
|
|
||||||
|
$returnTo = (string) $this->request->getPost('return_to');
|
||||||
|
if ($returnTo === 'all') {
|
||||||
|
return redirect()->to(site_url('admin/feedback/all') . '#fb-' . $id)->with('success', '문의 내용을 수정했습니다.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->to(site_url('admin/feedback/' . $id))->with('success', '문의 내용을 수정했습니다.');
|
||||||
|
}
|
||||||
|
|
||||||
/** 스크린샷 이미지 서빙 (관리자만, writable 보호 유지) */
|
/** 스크린샷 이미지 서빙 (관리자만, writable 보호 유지) */
|
||||||
public function image(int $id): ResponseInterface
|
public function image(int $id): ResponseInterface
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,9 +20,24 @@ use App\Models\FeedbackModel;
|
|||||||
|
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-3 mt-2">
|
<div class="grid grid-cols-1 lg:grid-cols-2 gap-3 mt-2">
|
||||||
<section class="border border-gray-300 rounded-lg overflow-hidden">
|
<section class="border border-gray-300 rounded-lg overflow-hidden">
|
||||||
<div class="px-3 py-2 border-b bg-gray-50 text-sm font-semibold text-gray-700">의견 내용</div>
|
<div class="px-3 py-2 border-b bg-gray-50 text-sm font-semibold text-gray-700 flex items-center justify-between">
|
||||||
|
<span>의견 내용</span>
|
||||||
|
<button type="button" id="fb-content-edit-btn" class="text-xs font-medium text-blue-600 hover:underline">수정</button>
|
||||||
|
</div>
|
||||||
<div class="p-3 space-y-2 text-sm">
|
<div class="p-3 space-y-2 text-sm">
|
||||||
<p class="whitespace-pre-wrap text-gray-800"><?= esc((string) $row->fb_content) ?></p>
|
<!-- 보기 모드 -->
|
||||||
|
<div id="fb-content-view">
|
||||||
|
<p class="whitespace-pre-wrap text-gray-800"><?= esc((string) $row->fb_content) ?></p>
|
||||||
|
</div>
|
||||||
|
<!-- 수정 모드 -->
|
||||||
|
<form id="fb-content-edit" action="<?= site_url('admin/feedback/' . (int) $row->fb_idx . '/content') ?>" method="post" class="hidden">
|
||||||
|
<?= csrf_field() ?>
|
||||||
|
<textarea name="fb_content" rows="6" maxlength="2000" class="w-full border border-gray-300 rounded px-2 py-1.5 text-sm"><?= esc((string) $row->fb_content) ?></textarea>
|
||||||
|
<div class="flex gap-2 mt-2">
|
||||||
|
<button type="submit" class="bg-btn-search text-white px-4 py-1.5 rounded-sm text-sm">수정 저장</button>
|
||||||
|
<button type="button" id="fb-content-cancel" class="bg-gray-200 text-gray-700 px-4 py-1.5 rounded-sm text-sm hover:bg-gray-300">취소</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<hr class="my-2"/>
|
<hr class="my-2"/>
|
||||||
<?php
|
<?php
|
||||||
// 화면 URL — embed 파라미터를 떼고 전체 화면 절대 URL로 변환(클릭 시 해당 화면으로 바로 이동).
|
// 화면 URL — embed 파라미터를 떼고 전체 화면 절대 URL로 변환(클릭 시 해당 화면으로 바로 이동).
|
||||||
@@ -91,3 +106,21 @@ use App\Models\FeedbackModel;
|
|||||||
</section>
|
</section>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div><!-- /.fb-selectable -->
|
</div><!-- /.fb-selectable -->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var btn = document.getElementById('fb-content-edit-btn');
|
||||||
|
var view = document.getElementById('fb-content-view');
|
||||||
|
var edit = document.getElementById('fb-content-edit');
|
||||||
|
var cancel = document.getElementById('fb-content-cancel');
|
||||||
|
if (!btn || !view || !edit) return;
|
||||||
|
var show = function (editing) {
|
||||||
|
view.classList.toggle('hidden', editing);
|
||||||
|
edit.classList.toggle('hidden', !editing);
|
||||||
|
btn.classList.toggle('hidden', editing);
|
||||||
|
if (editing) { var ta = edit.querySelector('textarea'); if (ta) ta.focus(); }
|
||||||
|
};
|
||||||
|
btn.addEventListener('click', function () { show(true); });
|
||||||
|
if (cancel) cancel.addEventListener('click', function () { show(false); });
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user