create.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. <template>
  2. <div class="admin--page-content">
  3. <div class="admin--form">
  4. <form @submit.prevent="handleSubmit" class="">
  5. <!-- 낚시분야 -->
  6. <table class="admin--form--table">
  7. <colgroup>
  8. <col style="width: 120px;">
  9. <col>
  10. </colgroup>
  11. <tbody>
  12. <tr>
  13. <th>
  14. <div>
  15. 지역명 <span class="admin--required">*</span>
  16. </div>
  17. </th>
  18. <td>
  19. <div class="input--wrap">
  20. <input
  21. v-model="formData.name"
  22. type="text"
  23. class="admin--form-input"
  24. placeholder="예: 부산/울산"
  25. required
  26. />
  27. <p>시도 단위 지역명. 1~20자. 인접 시도 통합 시 슬래시(/) 사용 (예: 충남/세종)</p>
  28. </div>
  29. </td>
  30. </tr>
  31. </tbody>
  32. </table>
  33. <div class="admin--info--box">
  34. <h3>💡 지역 등록 안내</h3>
  35. <ul>
  36. <li>지역 = 회원 가입 시 선호 지역 선택 + 낚시어선/낚시터 분류 기준</li>
  37. <li>중복 등록 차단. 인접 시도 통합 표기 권장 (예: "충남" 대신 "충남/세종")</li>
  38. </ul>
  39. </div>
  40. <!-- 버튼 영역 -->
  41. <div class="admin--form-actions">
  42. <button type="button" class="admin--btn" @click="goToList">
  43. ← 목록으로
  44. </button>
  45. <!-- <button type="button" class="admin--btn admin--btn-red-border ml--auto" @click="">
  46. 삭제
  47. </button> -->
  48. <button type="submit" class="admin--btn admin--btn-red ml--auto" :disabled="isSaving">
  49. {{ isSaving ? "저장 중..." : "저장" }}
  50. </button>
  51. </div>
  52. <!-- 성공/에러 메시지 -->
  53. <div v-if="successMessage" class="admin--alert admin--alert-success">
  54. {{ successMessage }}
  55. </div>
  56. <div v-if="errorMessage" class="admin--alert admin--alert-error">
  57. {{ errorMessage }}
  58. </div>
  59. </form>
  60. </div>
  61. </div>
  62. </template>
  63. <script setup>
  64. import { ref } from "vue";
  65. import { useRouter } from "vue-router";
  66. definePageMeta({
  67. layout: "admin",
  68. middleware: ["auth"],
  69. });
  70. const router = useRouter();
  71. const { post } = useApi();
  72. const isSaving = ref(false);
  73. const successMessage = ref("");
  74. const errorMessage = ref("");
  75. const formData = ref({
  76. name: "",
  77. });
  78. // 폼 제출
  79. const handleSubmit = async () => {
  80. successMessage.value = "";
  81. errorMessage.value = "";
  82. const name = formData.value.name.trim();
  83. // 유효성 검사
  84. if (!name) {
  85. errorMessage.value = "지역명을 입력하세요.";
  86. return;
  87. }
  88. if (name.length > 20) {
  89. errorMessage.value = "지역명은 20자 이내로 입력하세요.";
  90. return;
  91. }
  92. isSaving.value = true;
  93. try {
  94. const { data, error } = await post("/area", { name });
  95. if (error || !data?.success) {
  96. errorMessage.value = error?.message || data?.message || "등록에 실패했습니다.";
  97. } else {
  98. successMessage.value = data.message || "낚시지역이 등록되었습니다.";
  99. setTimeout(() => {
  100. router.push("/site-manager/area/list");
  101. }, 1000);
  102. }
  103. } catch (error) {
  104. errorMessage.value = "서버 오류가 발생했습니다.";
  105. console.error("Save error:", error);
  106. } finally {
  107. isSaving.value = false;
  108. }
  109. };
  110. // 목록으로 이동
  111. const goToList = () => {
  112. router.push("/site-manager/area/list");
  113. };
  114. </script>