validate([ 'active' => ['nullable','in:0,1'], 'q' => ['nullable','string','max:120'], ]); $page = $this->service->listTemplates($filters, perPage: 20); return view('admin.mail.templates.index', [ 'templates' => $page, 'filters' => $filters, 'skins' => $this->service->getSkinOptions(), ]); } public function create() { return view('admin.mail.templates.form', [ 'mode' => 'create', 'tpl' => (object)[ 'id'=>null,'code'=>'','title'=>'','description'=>'', 'skin_key'=>'hero','subject'=>'','body'=>'', 'hero_image_url'=>'','cta_label'=>'','cta_url'=>'','is_active'=>1, ], 'skins' => $this->service->getSkinOptions(), ]); } public function store(Request $request) { $data = $this->validateTemplate($request, isCreate: true); $adminId = (int)auth('admin')->id(); $res = $this->service->createTemplate($adminId, $data); if (!$res['ok']) return back()->with('toast',['type'=>'danger','title'=>'실패','message'=>$res['message']])->withInput(); return redirect()->route('admin.mail.templates.index')->with('toast',['type'=>'success','title'=>'완료','message'=>'템플릿을 생성했습니다.']); } public function edit(int $id) { $tpl = $this->service->getTemplate($id); if (!$tpl) abort(404); return view('admin.mail.templates.form', [ 'mode' => 'edit', 'tpl' => $tpl, 'skins' => $this->service->getSkinOptions(), ]); } public function update(Request $request, int $id) { $data = $this->validateTemplate($request, isCreate: false); $adminId = (int)auth('admin')->id(); $res = $this->service->updateTemplate($adminId, $id, $data); if (!$res['ok']) return back()->with('toast',['type'=>'danger','title'=>'실패','message'=>$res['message']])->withInput(); return redirect()->route('admin.mail.templates.index')->with('toast',['type'=>'success','title'=>'완료','message'=>'템플릿을 수정했습니다.']); } private function validateTemplate(Request $request, bool $isCreate): array { $rules = [ 'skin_key' => ['required','in:hero,newsletter,minimal,clean,dark'], 'title' => ['required','string','max:120'], 'description' => ['nullable','string','max:255'], 'subject' => ['required','string','max:190'], 'body' => ['required','string','max:20000'], 'hero_image_url' => ['nullable','string','max:500'], 'cta_label' => ['nullable','string','max:80'], 'cta_url' => ['nullable','string','max:500'], 'is_active' => ['nullable','in:1'], ]; if ($isCreate) { $rules['code'] = ['required','string','min:3','max:60','regex:/^[a-zA-Z0-9_-]+$/']; } return $request->validate($rules); } }