어쩌다보니 프레이머에 code component를 만들게 되었는데, 어차피 만든 김에 구글 시트에 바로 정보를 쏘면 다른 써드파티 서비스를 추가로 결제하지 않아도 될 것 같다는 생각이 들었다. (게다가 대부분의 폼 서비스가 submission 단위로 결제를 요구하니 부담스럽기도 했다.)
일단 신청 폼을 만들고 제출 버튼을 누르면 완료 팝업이 뜨게끔 코드를 작성하고, 구글 스크립트에 doPost() 함수를 만들어 웹 서비스 배포를 했다.
// Welcome to Code in Framer
// Get Started: https://www.framer.com/developers/
import React, { useState, useEffect } from "react"
import Example from "https://framer.com/m/framer/Example.js@^1.0.0"
// Modal component
const Modal = ({ message, onClose }) => {
return (
<div
style={{
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100%",
background: "rgba(0, 0, 0, 0.5)",
display: "flex",
zIndex: 9999,
alignItems: "center",
justifyContent: "center",
}}
>
<div
style={{
background: "white",
padding: "30px",
borderRadius: "8px",
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.1)",
display: "flex",
flexDirection: "column",
alignItems: "center",
zIndex: 10000,
}}
>
<p>{message}</p>
<button
onClick={onClose}
style={{
width: "140px",
background: "#111111",
color: "white",
padding: "8px 16px",
border: "none",
borderRadius: "4px",
cursor: "pointer",
marginTop: "12px",
}}
>
확인
</button>
</div>
</div>
)
}
export default function Form(props) {
const [isModalVisible, setIsModalVisible] = useState(false)
const handleSubmit = async (event) => {
event.preventDefault()
const nameInput = document.getElementById("name") as HTMLInputElement
const phoneInput = document.getElementById("number") as HTMLInputElement
const addressTextarea = document.getElementById(
"message"
) as HTMLTextAreaElement
const formData = {
name: nameInput.value,
phone: phoneInput.value,
address: addressTextarea.value,
}
const response = await fetch(
"GOOGLE_APPS_SCRIPT_WEBAPP_URL",
{
method: "POST",
mode: "no-cors",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
}
)
setIsModalVisible(true)
}
const handleKeyboardOpen = () => {
const viewportMeta = document.querySelector(
'meta[name="viewport"]'
) as HTMLMetaElement
if (viewportMeta) {
viewportMeta.content =
"width=device-width, initial-scale=1, maximum-scale=1"
}
}
const handleKeyboardClose = () => {
const viewportMeta = document.querySelector(
'meta[name="viewport"]'
) as HTMLMetaElement
if (viewportMeta) {
viewportMeta.content =
"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
}
}
useEffect(() => {
window.addEventListener("resize", handleKeyboardOpen)
window.addEventListener("orientationchange", handleKeyboardOpen)
window.addEventListener("focusin", handleKeyboardOpen)
window.addEventListener("focusout", handleKeyboardClose)
return () => {
window.removeEventListener("resize", handleKeyboardOpen)
window.removeEventListener("orientationchange", handleKeyboardOpen)
window.removeEventListener("focusin", handleKeyboardOpen)
window.removeEventListener("focusout", handleKeyboardClose)
}
}, [])
return (
<div>
<form
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
fontFamily: "Inter, sans-serif",
fontSize: "18px",
color: "RED",
padding: "24px",
backgroundColor: "white",
borderRadius: "8px",
boxShadow: "0 0 8px 0 rgba(0, 0, 0, 0.0)",
}}
onSubmit={handleSubmit}
>
<input
type="text"
id="name"
name="name"
placeholder="1.입력란"
required
style={{
width: "100%",
padding: "16px",
marginBottom: "12px",
border: "1px solid #ccc",
borderRadius: "8px",
}}
/>
<input
type="text"
id="number"
name="phone"
placeholder="2.입력란"
required
style={{
width: "100%",
padding: "16px",
marginBottom: "12px",
border: "1px solid #ccc",
borderRadius: "8px",
}}
/>
<textarea
type="textarea"
rows="4"
id="message"
name="message"
placeholder="3.입력란"
required
style={{
width: "100%",
padding: "16px",
marginBottom: "12px",
border: "1px solid #ccc",
borderRadius: "8px",
}}
/>
<input
type="submit"
value="제출"
style={{
fontSize: "16px",
fontFamily: "Manrope, sans serif",
width: "100%",
padding: "16px",
backgroundColor: "#111111",
color: "white",
fontWeight: "bold",
border: "none",
borderRadius: "8px",
cursor: "pointer",
}}
/>
<p
style={{
fontFamily: "Manrope, sans-serif",
fontWeight: "500",
color: "#666666",
fontSize: "9px",
lineHeight: "1.5",
textAlign: "left",
marginTop: "8px", // Add some space from the button
}}
>
덧붙이고 싶은 라벨은 여기에
</p>
</form>
{isModalVisible && (
<Modal
message="팝업 메세지 입력하기"
onClose={() => setIsModalVisible(false)}
/>
)}
</div>
)
}
// Styles are written in object syntax
// Learn more: https://reactjs.org/docs/dom-elements.html#style
const containerStyle = {
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
}
그리고 구글 스크립트에 아래의 함수를 만들면 POST 요청에 따라 doPost 함수가 호출된다. 이때 배포 과정을 꼭 거쳐야 한다. SHEET_ID는 구글 스프레드 시트 URL 뒷 부분에 자리한 값이다.
function doPost(e) {
var sheet = SpreadsheetApp.openById('SHEET_ID').getActiveSheet();
var data = JSON.parse(e.postData.contents);
var row = [new Date(), data.name, data.phone, data.address];
sheet.appendRow(row);
return ContentService.createTextOutput('Success').setMimeType(ContentService.MimeType.TEXT);
}
여기까지 완료되면 각각의 코드의 GOOGLE_APPS_SCRIPT_WEBAPP_URL 를 넣어주면 끝난다.
'코드와 오류 기록' 카테고리의 다른 글
git push RPC failed disconnect while reading sideband packet (0) | 2024.08.20 |
---|---|
Framer에서 OS별로 버튼 출력여부 결정하기 (0) | 2023.08.29 |
pytorch를 이용한 운동 자세 확인 (0) | 2023.08.15 |
SD roop 설정 (0) | 2023.08.10 |
SD pip install 수동으로 해주기 (0) | 2023.08.10 |