신사(SinSa)
article thumbnail

어쩌다보니 프레이머에 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 를 넣어주면 끝난다.

profile

신사(SinSa)

@신사(SinSa)

포스팅이 좋았다면 "좋아요❤️" 눌러주세요!