견적문의 추가
This commit is contained in:
54
src/main/java/com/owrawww/controller/QuoteController.java
Normal file
54
src/main/java/com/owrawww/controller/QuoteController.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package com.owrawww.controller;
|
||||||
|
|
||||||
|
import com.owrawww.domain.Quote;
|
||||||
|
import com.owrawww.service.QuoteService;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/bbs/insertQuote")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class QuoteController {
|
||||||
|
|
||||||
|
private final QuoteService quoteService;
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public String quoteForm(@ModelAttribute Quote quote) {
|
||||||
|
return "insertQuote";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@ResponseBody
|
||||||
|
public ResponseEntity<Map<String, Object>> quoteSubmit(@Valid @ModelAttribute Quote quote,
|
||||||
|
BindingResult bindingResult) {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
if (bindingResult.hasErrors()) {
|
||||||
|
List<String> errors = bindingResult.getFieldErrors().stream()
|
||||||
|
.map(e -> e.getField() + ": " + e.getDefaultMessage())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
result.put("success", false);
|
||||||
|
result.put("message", "입력값을 확인해주세요.");
|
||||||
|
result.put("errors", errors);
|
||||||
|
return ResponseEntity.badRequest().body(result);
|
||||||
|
}
|
||||||
|
boolean success = quoteService.submit(quote);
|
||||||
|
result.put("success", success);
|
||||||
|
if (!success) {
|
||||||
|
result.put("message", "처리 중 오류가 발생했습니다. 다시 시도해주세요.");
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/main/java/com/owrawww/domain/Quote.java
Normal file
47
src/main/java/com/owrawww/domain/Quote.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package com.owrawww.domain;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.Email;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Quote {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@NotBlank(message = "성명을 입력해주세요.")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotBlank(message = "이메일을 입력해주세요.")
|
||||||
|
@Email(message = "올바른 이메일 형식이 아닙니다.")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@NotBlank(message = "연락처를 입력해주세요.")
|
||||||
|
@Pattern(regexp = "^[0-9\\-+\\s]{7,20}$", message = "연락처 형식이 올바르지 않습니다.")
|
||||||
|
private String tel;
|
||||||
|
|
||||||
|
@NotBlank(message = "제목을 입력해주세요.")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@NotBlank(message = "내용을 입력해주세요.")
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
private String code;
|
||||||
|
private String comment;
|
||||||
|
private Integer topCode;
|
||||||
|
private Integer leftCode;
|
||||||
|
private Integer subGubun;
|
||||||
|
private Integer depth;
|
||||||
|
private String telHash;
|
||||||
|
private String emailHash;
|
||||||
|
private String SolutionGubun;
|
||||||
|
|
||||||
|
}
|
||||||
9
src/main/java/com/owrawww/domain/mapper/QuoteMapper.java
Normal file
9
src/main/java/com/owrawww/domain/mapper/QuoteMapper.java
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package com.owrawww.domain.mapper;
|
||||||
|
|
||||||
|
import com.owrawww.domain.Quote;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface QuoteMapper {
|
||||||
|
int insert(Quote quote);
|
||||||
|
}
|
||||||
34
src/main/java/com/owrawww/service/QuoteService.java
Normal file
34
src/main/java/com/owrawww/service/QuoteService.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package com.owrawww.service;
|
||||||
|
|
||||||
|
import com.owrawww.domain.Quote;
|
||||||
|
import com.owrawww.domain.mapper.QuoteMapper;
|
||||||
|
import com.owrawww.util.AesUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class QuoteService {
|
||||||
|
|
||||||
|
private final QuoteMapper quoteMapper;
|
||||||
|
private final AesUtil aesUtil;
|
||||||
|
|
||||||
|
public boolean submit(Quote quote) {
|
||||||
|
Quote saved = new Quote();
|
||||||
|
saved.setCode("3");
|
||||||
|
saved.setTitle(quote.getTitle());
|
||||||
|
saved.setComment(quote.getContent());
|
||||||
|
saved.setName(quote.getName());
|
||||||
|
saved.setTel(aesUtil.encrypt(quote.getTel()));
|
||||||
|
saved.setTelHash(aesUtil.hash(quote.getTel()));
|
||||||
|
saved.setEmail(aesUtil.encrypt(quote.getEmail()));
|
||||||
|
saved.setEmailHash(aesUtil.hash(quote.getEmail()));
|
||||||
|
saved.setTopCode(1);
|
||||||
|
saved.setLeftCode(5);
|
||||||
|
saved.setSubGubun(1);
|
||||||
|
saved.setDepth(1);
|
||||||
|
saved.setSolutionGubun("SOL001");
|
||||||
|
|
||||||
|
return quoteMapper.insert(saved) > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/main/resources/mapper/QuoteMapper.xml
Normal file
12
src/main/resources/mapper/QuoteMapper.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
|
||||||
|
<mapper namespace="com.owrawww.domain.mapper.QuoteMapper">
|
||||||
|
|
||||||
|
<insert id="insert" parameterType="com.owrawww.domain.Quote" useGeneratedKeys="true" keyProperty="id">
|
||||||
|
INSERT INTO application_table (code, title, name, phone, tel_hash, email, email_hash, comment, depth, in_date, top_code, left_code, sub_gubun,solution_gubun)
|
||||||
|
VALUES (#{code}, #{title}, #{name}, #{tel}, #{telHash}, #{email}, #{emailHash}, #{comment}, #{depth}, now(), #{topCode}, #{leftCode}, #{subGubun}, #{solutionGubun})
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -1,32 +1,15 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="ko">
|
<html lang="ko"
|
||||||
|
xmlns:th="http://www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{layout/default}">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<title>PG업 등록</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=yes">
|
<!-- 이 페이지 전용 CSS -->
|
||||||
<meta name="format-detection" content="telephone=no">
|
|
||||||
<title>회사소개 - 오라인포</title>
|
|
||||||
|
|
||||||
<script src="/js/jquery-3.7.1.min.js"></script>
|
|
||||||
<script src="/js/jquery-ui-1.13.3.min.js"></script>
|
|
||||||
<script src="/js/topmenu_script.js"></script>
|
|
||||||
<script src="/js/swiper.min.js"></script>
|
|
||||||
<script src="/js/aos.js"></script>
|
|
||||||
<script src="/js/gsap.min.js"></script>
|
|
||||||
<script src="/js/ScrollTrigger.min.js"></script>
|
|
||||||
<link rel="icon" href="/img/common/favicon.ico" type="image/x-icon">
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/img/common/apple-touch-icon.png">
|
|
||||||
<link rel="stylesheet" href="/css/common.css">
|
|
||||||
<link rel="stylesheet" href="/css/sub.css">
|
|
||||||
<link rel="stylesheet" href="/css/aos.css">
|
|
||||||
<link rel="stylesheet" href="/css/swiper.min.css">
|
|
||||||
<script src="/js/feather.min.js"></script> <!-- feather 아이콘-->
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap" rel="stylesheet"> <!-- 영문폰트 -->
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" /> <!--구글머티리얼 아이콘-->
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="wrapper">
|
<div id="wrapper" layout:fragment="content">
|
||||||
|
|
||||||
<!-- ======================== HEADER -->
|
<!-- ======================== HEADER -->
|
||||||
<header id="hd" class="sub"></header>
|
<header id="hd" class="sub"></header>
|
||||||
@@ -279,7 +262,7 @@
|
|||||||
<svg viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
<svg viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
||||||
PG시스템 상세보기
|
PG시스템 상세보기
|
||||||
</a>
|
</a>
|
||||||
<a href="/bbs/partnership" class="evpg-btn-outline">
|
<a href="/bbs/insertQuote" class="evpg-btn-outline">
|
||||||
<svg viewBox="0 0 24 24"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
|
<svg viewBox="0 0 24 24"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
|
||||||
견적 문의하기
|
견적 문의하기
|
||||||
</a>
|
</a>
|
||||||
@@ -296,39 +279,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer id="ft"></footer>
|
<th:block layout:fragment="scripts">
|
||||||
<!-- 퀵메뉴 -->
|
|
||||||
<div id="quick_wrap" class="quick_wrap">
|
|
||||||
<div class="quick-menu">
|
|
||||||
<ul class="quick_list">
|
|
||||||
<li>
|
|
||||||
<a href="https://www.owra.net/etc/solution" target="_blank">
|
|
||||||
<div class="icon_img"><img src="/img/common/pg_bn.png" alt="선 정산 서비스"></div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://holaedu.co.kr/" target="_blank">
|
|
||||||
<div class="icon_img"><img src="/img/common/hola_bn.png" alt="hola"></div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="delivera.co.kr" target="_blank">
|
|
||||||
<div class="icon_img"><img src="/img/common/del_bn.png" alt="배달시대"></div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#">
|
|
||||||
<div class="icon_img"><img src="/img/common/ing_bg.png" alt="현재 진행 프로젝트"></div>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<a href="#" class="top_btn pc"><span class="material-symbols-outlined">arrow_upward</span> TOP</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="/js/sub.js"></script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* 스크롤 페이드업 */
|
/* 스크롤 페이드업 */
|
||||||
const _obs = new IntersectionObserver(entries => {
|
const _obs = new IntersectionObserver(entries => {
|
||||||
@@ -344,5 +295,4 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</th:block>
|
||||||
</html>
|
|
||||||
324
src/main/resources/templates/insertQuote.html
Normal file
324
src/main/resources/templates/insertQuote.html
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="ko"
|
||||||
|
xmlns:th="http://www.thymeleaf.org"
|
||||||
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
|
layout:decorate="~{layout/default}">
|
||||||
|
<head>
|
||||||
|
<title>PG견적문의</title>
|
||||||
|
<body class="page-inquiry" >
|
||||||
|
|
||||||
|
<div id="wrapper" layout:fragment="content">
|
||||||
|
|
||||||
|
<!-- ======================== HEADER -->
|
||||||
|
<header id="hd" class="sub"></header>
|
||||||
|
|
||||||
|
<!-- ======================== CONTAINER -->
|
||||||
|
<div id="container">
|
||||||
|
<div id="container_wrapper">
|
||||||
|
<!-- ========= SUB CONTENT [s] ========= -->
|
||||||
|
|
||||||
|
<div class="sub_content sec-recreuit">
|
||||||
|
<div class="sub-section2">
|
||||||
|
<div class="sub-inner">
|
||||||
|
<div data-aos="fade-up">
|
||||||
|
<h2 class="sub-h2 text-center">
|
||||||
|
PG 견적 문의
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="inquiry-wrap">
|
||||||
|
|
||||||
|
<!-- 좌측 타이틀 -->
|
||||||
|
<aside class="inquiry-aside" aria-label="폼 안내">
|
||||||
|
<h2 class="inquiry-aside__title" data-aos="fade-up">
|
||||||
|
견적문의
|
||||||
|
</h2>
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
<!-- 우측 폼 -->
|
||||||
|
<div class="inquiry-form" role="main" data-aos="fade-up">
|
||||||
|
<form id="inquiryForm" th:action="@{/bbs/insertQuote}" method="post" novalidate>
|
||||||
|
|
||||||
|
<!-- Row 1: 성명 + 이메일 -->
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="inp_name">
|
||||||
|
성명
|
||||||
|
<span class="required" aria-hidden="true">*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="inp_name"
|
||||||
|
name="name"
|
||||||
|
class="form-input"
|
||||||
|
placeholder="성함을 입력해주세요."
|
||||||
|
autocomplete="name"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="form-error-msg" role="alert" id="err_name">성명을 입력해주세요.</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="inp_email">
|
||||||
|
이메일
|
||||||
|
<span class="required" aria-hidden="true">*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
id="inp_email"
|
||||||
|
name="email"
|
||||||
|
class="form-input"
|
||||||
|
placeholder="이메일을 입력해주세요."
|
||||||
|
autocomplete="email"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="form-error-msg" role="alert" id="err_email">올바른 이메일을 입력해주세요.</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Row 2: 연락처 + 지원분야 -->
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="inp_tel">
|
||||||
|
연락처
|
||||||
|
<span class="required" aria-hidden="true">*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="tel"
|
||||||
|
id="inp_tel"
|
||||||
|
name="tel"
|
||||||
|
class="form-input"
|
||||||
|
placeholder="연락처를 입력해주세요."
|
||||||
|
autocomplete="tel"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="form-error-msg" role="alert" id="err_tel">연락처를 입력해주세요.</span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Row 3: 제목 -->
|
||||||
|
<div class="form-row form-row--full">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="inp_title">
|
||||||
|
제목
|
||||||
|
<span class="required" aria-hidden="true">*</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="inp_title"
|
||||||
|
name="title"
|
||||||
|
class="form-input"
|
||||||
|
placeholder="제목을 입력해주세요."
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<span class="form-error-msg" role="alert" id="err_title">제목을 입력해주세요.</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Row 4: 내용 -->
|
||||||
|
<div class="form-row form-row--full">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label" for="inp_content">
|
||||||
|
내용
|
||||||
|
<span class="required" aria-hidden="true">*</span>
|
||||||
|
</label>
|
||||||
|
<textarea
|
||||||
|
id="inp_content"
|
||||||
|
name="content"
|
||||||
|
class="form-textarea"
|
||||||
|
placeholder="문의내용을 입력해주세요."
|
||||||
|
required
|
||||||
|
></textarea>
|
||||||
|
<span class="form-error-msg" role="alert" id="err_content">내용을 입력해주세요.</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 개인정보 수집 및 이용 안내 -->
|
||||||
|
<div class="privacy-section">
|
||||||
|
<h3 class="privacy-section__title">개인정보 수집 및 이용 안내</h3>
|
||||||
|
<div class="privacy-box" tabindex="0" aria-label="개인정보 수집 및 이용 안내 내용">
|
||||||
|
<p>(주)오라인포는 아래의 목적으로 개인정보를 수집 및 이용하며, 방문자의 개인정보를 안전하게 취급하는데 최선을 다합니다.</p>
|
||||||
|
<p>
|
||||||
|
<strong>1. 수집목적</strong>
|
||||||
|
– 원활한 서비스를 위한 이용자 식별<br>
|
||||||
|
– 문의사항(광고제휴, 채용문의)의 처리 및 결과 통보
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>2. 수집항목</strong>
|
||||||
|
– 필수항목 : 성명, 이메일, 연락처, 제목, 문의내용<br>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>3. 보유 및 이용기간</strong>
|
||||||
|
– 수집된 개인정보는 수집 및 이용 목적이 달성된 후 지체없이 파기합니다.<br>
|
||||||
|
– 단, 관련 법령에 의거하여 일정 기간 보존이 필요한 경우 해당 기간 동안 보관합니다.
|
||||||
|
</p>
|
||||||
|
<p>귀하는 개인정보 수집·이용에 대한 동의를 거부할 권리가 있으며, 동의 거부 시 채용문의 및 입사지원 서비스 이용이 제한됩니다.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 동의 체크박스 -->
|
||||||
|
<label class="form-agree" id="agreeLabel">
|
||||||
|
<span class="form-agree__cb">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id="inp_agree"
|
||||||
|
name="agree"
|
||||||
|
required
|
||||||
|
aria-required="true"
|
||||||
|
aria-describedby="err_agree"
|
||||||
|
>
|
||||||
|
<span class="cb-custom" aria-hidden="true"></span>
|
||||||
|
</span>
|
||||||
|
<span class="form-agree__label">
|
||||||
|
개인정보 수집·이용에 대해 동의합니다.
|
||||||
|
<span class="required" aria-hidden="true">*</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<span class="form-error-msg" role="alert" id="err_agree">개인정보 수집·이용에 동의해주세요.</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 접수하기 버튼 -->
|
||||||
|
<div class="form-submit-wrap">
|
||||||
|
<button type="submit" class="form-submit-btn" aria-label="견적문의 접수하기">
|
||||||
|
견적 문의하기
|
||||||
|
<span class="btn-arrow material-symbols-outlined" aria-hidden="true">arrow_forward</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<!-- // 우측 폼 -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- // 채용문의 & 입사지원 폼 -->
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- ========= SUB CONTENT [e] ========= -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<th:block layout:fragment="scripts">
|
||||||
|
<script>
|
||||||
|
/* ========================== 제휴문의 폼 */
|
||||||
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
const $form = $('#inquiryForm');
|
||||||
|
|
||||||
|
/* ---- 유효성 검사 규칙 ---- */
|
||||||
|
const validators = {
|
||||||
|
name: { el: '#inp_name', err: '#err_name', check: function (v) { return v.trim().length > 0; } },
|
||||||
|
email: { el: '#inp_email', err: '#err_email', check: function (v) { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v.trim()); } },
|
||||||
|
tel: { el: '#inp_tel', err: '#err_tel', check: function (v) { return /^[0-9\-+\s]{7,20}$/.test(v.trim()); } },
|
||||||
|
dept: { el: '#inp_dept', err: '#err_dept', check: function (v) { return v !== '' && v !== null; } },
|
||||||
|
title: { el: '#inp_title', err: '#err_title', check: function (v) { return v.trim().length > 0; } },
|
||||||
|
content: { el: '#inp_content', err: '#err_content', check: function (v) { return v.trim().length > 0; } },
|
||||||
|
agree: { el: '#inp_agree', err: '#err_agree', check: function () { return $('#inp_agree').is(':checked'); } }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---- 단일 필드 유효성 표시 ---- */
|
||||||
|
function validateField(key) {
|
||||||
|
const rule = validators[key];
|
||||||
|
const $el = $(rule.el);
|
||||||
|
const $err = $(rule.err);
|
||||||
|
const val = key === 'agree' ? '' : $el.val();
|
||||||
|
const ok = rule.check(val);
|
||||||
|
$el.toggleClass('is-error', !ok);
|
||||||
|
$err.toggleClass('is-show', !ok);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- 실시간 검사 ---- */
|
||||||
|
$.each(validators, function (key, rule) {
|
||||||
|
const $el = $(rule.el);
|
||||||
|
const evt = (key === 'dept' || key === 'agree') ? 'change' : 'input';
|
||||||
|
$el.on(evt, function () { validateField(key); });
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ---- 연락처: 숫자·하이픈·공백·+만 입력 허용 ---- */
|
||||||
|
$('#inp_tel').on('input', function () {
|
||||||
|
this.value = this.value.replace(/[^0-9\-+\s]/g, '');
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ---- 폼 제출 ---- */
|
||||||
|
$form.on('submit', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
let allOk = true;
|
||||||
|
$.each(validators, function (key) {
|
||||||
|
if (!validateField(key)) allOk = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!allOk) {
|
||||||
|
const $firstErr = $form.find('.is-error').first();
|
||||||
|
if ($firstErr.length) {
|
||||||
|
$firstErr[0].focus();
|
||||||
|
$('html, body').animate({ scrollTop: $firstErr.offset().top - 120 }, 300);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 유효성 통과 시 AJAX 제출 */
|
||||||
|
const $btn = $form.find('[type="submit"]');
|
||||||
|
$btn.prop('disabled', true);
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: $form.attr('action'),
|
||||||
|
method: 'POST',
|
||||||
|
data: $form.serialize(),
|
||||||
|
success: function (res) {
|
||||||
|
if (res.success) {
|
||||||
|
showInquiryModal();
|
||||||
|
} else {
|
||||||
|
alert(res.message || '처리 중 오류가 발생했습니다. 다시 시도해주세요.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
alert('처리 중 오류가 발생했습니다. 다시 시도해주세요.');
|
||||||
|
},
|
||||||
|
complete: function () {
|
||||||
|
$btn.prop('disabled', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/* ---- 완료 모달 ---- */
|
||||||
|
function showInquiryModal() {
|
||||||
|
if ($('#inquiryModal').length === 0) {
|
||||||
|
$('body').append(`
|
||||||
|
<div id="inquiryModal" role="dialog" aria-modal="true" aria-labelledby="modalTitle" style="display:none;">
|
||||||
|
<div class="inquiry-modal__backdrop"></div>
|
||||||
|
<div class="inquiry-modal__box">
|
||||||
|
<span class="inquiry-modal__icon material-symbols-outlined">check_circle</span>
|
||||||
|
<h3 class="inquiry-modal__title" id="modalTitle">문의가 접수되었습니다</h3>
|
||||||
|
<p class="inquiry-modal__desc">빠른 시일 내에 담당자가<br>연락드리겠습니다.</p>
|
||||||
|
<button type="button" class="inquiry-modal__close" id="inquiryModalClose">확인</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`);
|
||||||
|
$(document).on('click', '#inquiryModalClose, .inquiry-modal__backdrop', function () {
|
||||||
|
closeInquiryModal();
|
||||||
|
});
|
||||||
|
$(document).on('keydown', function (e) {
|
||||||
|
if (e.key === 'Escape' && $('#inquiryModal').is(':visible')) closeInquiryModal();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
$('#inquiryModal').css('display', 'flex').hide().fadeIn(200);
|
||||||
|
$('#inquiryModalClose').focus();
|
||||||
|
$('body').css('overflow', 'hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeInquiryModal() {
|
||||||
|
$('#inquiryModal').fadeOut(200);
|
||||||
|
$('body').css('overflow', '');
|
||||||
|
$form[0].reset();
|
||||||
|
$form.find('.is-error').removeClass('is-error');
|
||||||
|
$form.find('.form-error-msg.is-show').removeClass('is-show');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</th:block>
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
<li>2차 면접 : 1차 서류 전형 완료 후 합격자에 한해 개별 연락</li>
|
<li>2차 면접 : 1차 서류 전형 완료 후 합격자에 한해 개별 연락</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="ri-apply-wrap">
|
<div class="ri-apply-wrap">
|
||||||
<a href="#" class="ri-apply-btn">
|
<a href="/careers/recruitment" class="ri-apply-btn">
|
||||||
지원하기
|
지원하기
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||||
<line x1="5" y1="12" x2="19" y2="12"/>
|
<line x1="5" y1="12" x2="19" y2="12"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user