본문 바로가기
학원수업/4월

4/18 국비학원 개발자과정 - 실시간 데이터베이스, fullcalendar 달력 구현하기

by 코딩마스터^^ 2023. 4. 18.

파이어베이스의 실시간 데이터베이스를 사용하기위해 const database를 export해준다.

 

파이어베이스에 있는 데이터 가져오기

database와 ref임포트 해준다.

 

데이터 구조분해할당....

다시 연습해보기

memoRow로 넘겨서 하나씩 정보 꺼내기

 

공공데이터 활용 실습

https://www.data.go.kr/data/15000414/openapi.do

 

서울특별시_대중교통환승경로 조회 서비스

목적지로의 이동 경로에 대한 정보 제공

www.data.go.kr

서울특별시 오픈 api서비스 신청하고 승인을 기다린다.

승인이 되면 키가 발급된다.

포스트맨에서 확인해보려는데 방금 발급 받아서 그런지 안되네.

 

다시 fullcalendar 실시간 데이터 베이스

   import moment from 'moment';
   import React, { useState } from 'react'
   import { Button, Form, Modal, Table } from 'react-bootstrap'
   import Datetime from 'react-datetime';
   import { database } from '../../service/firebase'
   import { off, onValue, ref, set} from 'firebase/database'
   import { useEffect } from 'react';
   import MemoRow from './MemoRow';
   const MemoList = () => {
    //오늘 이전날짜 비활성화 처리하기
    const yesterday = moment().subtract(1, 'day')
    const valid = (current) => {
      return current.isAfter(yesterday);
    }
    const [show, setShow]=useState(false)//모달창초기값
    const handleClose=()=>setShow(false)//모달창닫기
    const handleShow=()=>setShow(true)//모달창보여주기
    //사용자로부터 입력받은 값-상태훅으로 관리하기
    const [m_no,setM_no]=useState(0)//식별자
    const [m_title,setM_title]=useState('')//일정명
    const [m_writer,setM_writer]=useState(0)//작성자
    const [m_content,setM_content]=useState(0)//일정내용
    const [m_start,setM_start]=useState('')
    const [m_end, setM_end]=useState('')
    const [memo, setMemo]=useState({
      m_no:0,
      m_title:'',
      m_writer:'',
      m_content:'',
      m_start:'',
      m_end:''
    })
    //시작날짜시간
    const handleStart=(date)=>{
      console.log(date);
      const m_start=moment(date._d).format('YYYY-MM-DD, a h:mm')
      console.log(m_start);
      setM_start(m_start)
    }
    //끝날자시간
    const handleEnd=(date)=>{
      console.log(date);
      const m_end=moment(date._d).format('YYYY-MM-DD, a h:mm')
      console.log(m_end);
      setM_start(m_end)
    }
    //화면에 입력받은 정보 담기
    const handleChangeForm=(event)=>{
       if(event.currentTarget==null){
        return
       }
      //  console.log('폼내용 변경 발생 name:',event.target.name);
      //  console.log('폼내용 변경 발생 value:',event.target.value);
      setMemo({
        ...memo,
        m_no:Date.now(),//십진수 날짜 정보
        [event.target.name]:event.target.value
      })
      console.log(memo)
    }
    //일정등록하기구현
    const memoAdd=(event)=>{
    //버튼이기때문에 이벤트 버블링 사전처리
      event.preventDefault()
      console.log(memo)
      const pmemo={
        m_no:memo.m_no,
        m_title:memo.m_title,
        m_writer:memo.m_writer,
        m_content:memo.m_content,
        m_start:m_start,
        m_end:m_end
      }
      console.log(pmemo);
      //파이어베이스 실시간 디비넣기
      set(ref(database,'memo/'+memo.m_no), pmemo);
      handleClose()
    }
    //메모정보가져오기
    const [memos,setMemos]=useState({})
    useEffect(()=>{
      const startCountRef=ref(database,'memo')
      onValue(startCountRef,(snapshot)=>{
        const data=snapshot.val()
        setMemos(data)
        return()=>off(startCountRef)
      })
    },[])
    const memoSearch=()=>{

    }
    const getMemoList=()=>{

    }
    const handleForm=()=>{

    }
     return (
       <>
   <div className="container">
      <div className="page-header">
        <h2>
          일정관리 <small>일정목록</small>
        </h2>
        <hr />
      </div>

      <div className="row">
        <div className="col-3">
          <select id="gubun" className="form-select" aria-label="분류선택">
            <option defaultValue>분류선택</option>
            <option value="m_title">일정명</option>
            <option value="m_writer">작성자</option>
            <option value="m_content">내용</option>
          </select>
        </div>
        <div className="col-6">
          <input
            type="text"
            id="keyword"
            className="form-control"
            placeholder="검색어를 입력하세요"
            aria-label="검색어를 입력하세요"
            aria-describedby="btn_search"
          />
        </div>
        <div className="col-3">
          <Button variant="danger" id="btn_search" onClick={memoSearch}>
            검색
          </Button>
        </div>
      </div>

      <div className="book-list">
        <Table striped bordered hover>
          <thead>
            <tr>
              <th>#</th>
              <th>일정명</th>
              <th>작성자</th>
              <th>일정시간</th>
            </tr>
          </thead>
          <tbody>
            {memos&&//데이터가 한건도 없는 경우를 고려
            Object.keys(memos).map((key)=>(
              <MemoRow key={key} memo={memos[key]}/>
            ))
            }
          </tbody>
        </Table>
        <hr />
        <div className="booklist-footer">
          <Button variant="warning" onClick={getMemoList}>
            전체조회
          </Button>
          &nbsp;
          <Button variant="success" onClick={handleShow}>
            글쓰기
          </Button>
        </div>
      </div>
    </div>
    {/* ========================== [[  일정등록 Modal ]] ========================== */}
    <Modal show={show} onHide={handleClose} animation={true}>
        <Modal.Header closeButton>
          <Modal.Title>새로운 일정</Modal.Title>
        </Modal.Header>
        <Modal.Body>
        <Form id="f_memo">         
          <Form.Group className="mb-3 row" controlId="mTitle">
            <Form.Label className="col-sm-2 col-form-label">일정명</Form.Label>
            <div className='col-sm-10'>
            <Form.Control className='form-control form-control-sm' type="text" name="m_title" onChange={handleChangeForm} placeholder="Enter 일정명" />
            </div>
          </Form.Group>
          <Form.Group className="mb-3 row" controlId="boardWriter">
            <Form.Label className="col-sm-2 col-form-label">등록자</Form.Label>
            <div className='col-sm-10'>
            <Form.Control type="text" name="m_writer" onChange={handleChangeForm} className='form-control form-control-sm' placeholder="Enter 작성자" />
            </div>
          </Form.Group>
          <Form.Group className="mb-3 row" controlId="edit-start">
            <Form.Label className="col-sm-2 col-form-label">시작</Form.Label>
            <div className='col-sm-10'>
            <Datetime dateFormat='YYYY-MM-DD' isValiDate={valid} name="m_start" onChange={handleStart}/>
            </div>
          </Form.Group>
          <Form.Group className="mb-3 row" controlId="edit-end">
            <Form.Label className="col-sm-2 col-form-label">끝</Form.Label>
            <div className='col-sm-10'>
              {/* 페이지 이동 처리? onChange로 하려고 datetime 씀? 이종간이다...*/}
            <Datetime dateFormat='YYYY-MM-DD' isValiDate={valid}  name="m_end" onChange={handleEnd}/>
            </div>
          </Form.Group>
          <Form.Group className="mb-3 row" controlId="boardContent">
            <Form.Label className="col-sm-2 col-form-label">내용</Form.Label>
            <div className='col-sm-10'>
            <textarea className="form-control" name='m_content' onChange={handleChangeForm} rows="3"></textarea>
            </div>
          </Form.Group>
        </Form>
        </Modal.Body>
        <Modal.Footer>
          <Button variant="secondary" onClick={handleClose}>
            닫기
          </Button>
          <Button variant="primary" onClick={memoAdd}>
            저장
          </Button>
        </Modal.Footer>
      </Modal>     
    {/* ========================== [[ 글등록 Modal ]] ========================== */}    
       </>
     )
   }
   export default MemoList
import { off, onValue, ref, remove, set } from 'firebase/database';
import moment from 'moment/moment'
import React, { useEffect, useState } from 'react'
import { Button, Card, Form, ListGroup, ListGroupItem, Modal, Table } from 'react-bootstrap'
   import Datetime from 'react-datetime';
   import {Link, useNavigate, useParams} from 'react-router-dom'
import { database } from '../../service/firebase';

const MemoDetail = () => {
  const navigate=useNavigate();
  //사용자가 선택한 로우 m_no
  const {m_no}=useParams()
  const [memo, setMemo]=useState({})
  //오늘 이전날짜 비활성화 처리하기
  const yesterday = moment().subtract(1, 'day')
  const valid = (current) => {
    return current.isAfter(yesterday);
  }
  const [show, setShow]=useState(false)//모달창초기값
  const handleClose=()=>setShow(false)//모달창닫기
  const handleShow=()=>setShow(true)//모달창보여주기
  //사용자로부터 입력받은 값-상태훅으로 관리하기
  const [m_title,setM_title]=useState('')//일정명
  const [m_writer,setM_writer]=useState(0)//작성자
  const [m_content,setM_content]=useState(0)//일정내용
  const [m_start,setM_start]=useState('')
  const [m_end, setM_end]=useState('')
  useEffect(()=>{
    const startCountRef=ref(database,'memo/'+m_no)
    onValue(startCountRef,(snapshot)=>{
      const data=snapshot.val()
      setMemo(data)
      return()=>off(startCountRef)
    })
  },[m_no])
//파이어베이스에서 수정 업데이트 똑같다
  const memoUpdate=(event)=>{
    event.preventDefault()
    const pmemo={
      m_no:m_no,
      m_title:memo.m_title,
      m_writer:memo.m_writer,
      m_content:memo.m_content,
      m_start:m_start?memo.m_start:m_start,
      m_end:m_end?memo.m_end:m_end
    }
    console.log(pmemo);
    set(ref(database,'memo/'+m_no),pmemo);
    handleClose()
  }

  const memoDelete=(event)=>{
    event.preventDefault()
    //실시간 디비 삭제
    remove(ref(database,'memo/'+m_no))
    navigate('/memo')
  }
  //시작날짜시간
  const handleStart=(date)=>{
    console.log(date);
    const m_start=moment(date._d).format('YYYY-MM-DD, a h:mm')
    console.log(m_start);
    setM_start(m_start)
  }
  //끝날자시간
  const handleEnd=(date)=>{
    console.log(date);
    const m_end=moment(date._d).format('YYYY-MM-DD, a h:mm')
    console.log(m_end);
    setM_start(m_end)
  }
  //화면에 입력받은 정보 담기
  const handleChangeForm=(event)=>{
     if(event.currentTarget==null){
      return
     }
    //  console.log('폼내용 변경 발생 name:',event.target.name);
    //  console.log('폼내용 변경 발생 value:',event.target.value);
    setMemo({
      ...memo,
      m_no:Date.now(),//십진수 날짜 정보
      [event.target.name]:event.target.value
    })
    console.log(memo)
  }
  
  return (
    <>
      <div className="container">
        <div className="page-header">
          <h2>
            일정관리 <small>일정보기</small>
          </h2>
          <hr />
        </div>
        <Card style={{ width: "58rem" }}>
          <Card.Header>{memo.m_title}</Card.Header>
          <ListGroup className="list-group-flush">
            <ListGroupItem>{memo.m_writer}</ListGroupItem>
            <ListGroupItem>{`${memo.m_start} ~ ${memo.m_end}`}</ListGroupItem>
            <ListGroupItem>{memo.m_content}</ListGroupItem>
          </ListGroup>
          <div className="detail-link">
            <Button variant="primary" onClick={handleShow}>
              수정
            </Button>
            &nbsp;
            <Button variant="primary" onClick={memoDelete}>
              삭제
            </Button>
            <Link to="/memo" className="nav-link">
              일정목록
            </Link>
          </div>
        </Card>
        <hr />
        {/* ========================== [[  일정등록 Modal ]] ========================== */}
        <Modal show={show} onHide={handleClose} animation={true}>
          <Modal.Header closeButton>
            <Modal.Title>일정 수정</Modal.Title>
          </Modal.Header>
          <Modal.Body>
            <Form id="f_memo">
              <Form.Group className="mb-3 row" controlId="mTitle">
                <Form.Label className="col-sm-2 col-form-label">
                  일정명
                </Form.Label>
                <div className="col-sm-10">
                  <Form.Control
                    className="form-control form-control-sm"
                    type="text"
                    name="m_title"
                    value={memo.m_title}
                    onChange={handleChangeForm}
                    placeholder="Enter 일정명"
                  />
                </div>
              </Form.Group>
              <Form.Group className="mb-3 row" controlId="boardWriter">
                <Form.Label className="col-sm-2 col-form-label">
                  등록자
                </Form.Label>
                <div className="col-sm-10">
                  <Form.Control
                    type="text"
                    name="m_writer"
                    value={memo.m_writer}
                    onChange={handleChangeForm}
                    className="form-control form-control-sm"
                    placeholder="Enter 작성자"
                  />
                </div>
              </Form.Group>
              <Form.Group className="mb-3 row" controlId="edit-start">
                <Form.Label className="col-sm-2 col-form-label">
                  시작
                </Form.Label>
                <div className="col-sm-10">
                  <Datetime
                    dateFormat="YYYY-MM-DD"
                    isValidDate={valid}
                    name="m_start"
                    value={memo.m_start}
                    onChange={handleStart}
                  />
                </div>
              </Form.Group>
              <Form.Group className="mb-3 row" controlId="edit-end">
                <Form.Label className="col-sm-2 col-form-label">끝</Form.Label>
                <div className="col-sm-10">
                  <Datetime
                    dateFormat="YYYY-MM-DD"
                    isValidDate={valid}
                    name="m_end"
                    value={memo.m_end}
                    onChange={handleEnd}
                  />
                </div>
              </Form.Group>
              <Form.Group className="mb-3 row" controlId="boardContent">
                <Form.Label className="col-sm-2 col-form-label">
                  내용
                </Form.Label>
                <div className="col-sm-10">
                  <textarea
                    className="form-control"
                    name="m_content"
                    value={memo.m_content}
                    onChange={handleChangeForm}
                    rows="3"
                  ></textarea>
                </div>
              </Form.Group>
            </Form>
          </Modal.Body>
          <Modal.Footer>
            <Button variant="secondary" onClick={handleClose}>
              닫기
            </Button>
            <Button variant="primary" onClick={memoUpdate}>
              저장
            </Button>
          </Modal.Footer>
        </Modal>
        {/* ========================== [[ 글등록 Modal ]] ========================== */}
      </div>
    </>
  )
}

export default MemoDetail
import React, { useState } from 'react'
import FullCalendar from '@fullcalendar/react' // must go before plugins
import dayGridPlugin from '@fullcalendar/daygrid' // a plugin!
import interactionPlugin from '@fullcalendar/interaction' // a plugin!
import { useEffect } from 'react'
import axios from 'axios'
import interaction from '@fullcalendar/interaction'
import { Button, Form, Modal } from 'react-bootstrap'
import Datetime from 'react-datetime';
import moment from 'moment/moment'

const SchedulePage = () => {
    //오늘 이전날짜 비활성화 처리하기
    const yesterday = moment().subtract(1, 'day')
    const valid = (current) => {
      return current.isAfter(yesterday);
    }
    const [show, setShow]=useState(false)//모달창초기값
    const handleClose=()=>setShow(false)//모달창닫기
    const handleShow=()=>setShow(true)//모달창보여주기
  const [memoList, setMemoList]=useState([])
  useEffect(()=>{
    axios.get("/schedule.json").then(res=>{
      console.log(res.data);
      setMemoList(res.data)//state Hook이 가지고 있는 것이고 실제 화면에 보이기 위해서는 리렌더링 필요함
    })
  },[])
  const handleDateClick=(arg)=>{
    console.log(arg.dateStr);
    handleShow();//모달창의 옵션값 true/false를 바꿔주는 함수
  }
  const handleChangeForm=()=>{
    
  }
  const memoAdd=()=>{

  }
  //시작날짜시간
  const handleStart=(date)=>{
    console.log(date);
    const start=moment(date._d).format('YYYY-MM-DD, a h:mm')
    console.log(start);
    
  }
  //끝날자시간
  const handleEnd=(date)=>{
    console.log(date);
    const end=moment(date._d).format('YYYY-MM-DD, a h:mm')
    console.log(end);
  
  }
  return (
    <>
      <FullCalendar
        plugins={[ dayGridPlugin, interactionPlugin ]}
        initialView="dayGridMonth"
        weekends={false}
        events={memoList}//샘플 값 대신 훅을 넣어준다.
        height={"100vh"}
        dateClick={handleDateClick}
      />
       {/* ========================== [[  일정등록 Modal ]] ========================== */}
    <Modal show={show} onHide={handleClose} animation={true}>
        <Modal.Header closeButton>
          <Modal.Title>새로운 일정</Modal.Title>
        </Modal.Header>
        <Modal.Body>
        <Form id="f_memo">         
          <Form.Group className="mb-3 row" controlId="mTitle">
            <Form.Label className="col-sm-2 col-form-label">일정명</Form.Label>
            <div className='col-sm-10'>
            <Form.Control className='form-control form-control-sm' type="text" name="m_title" onChange={handleChangeForm} placeholder="Enter 일정명" />
            </div>
          </Form.Group>
          <Form.Group className="mb-3 row" controlId="boardWriter">
            <Form.Label className="col-sm-2 col-form-label">등록자</Form.Label>
            <div className='col-sm-10'>
            <Form.Control type="text" name="m_writer" onChange={handleChangeForm} className='form-control form-control-sm' placeholder="Enter 작성자" />
            </div>
          </Form.Group>
          <Form.Group className="mb-3 row" controlId="edit-start">
            <Form.Label className="col-sm-2 col-form-label">시작</Form.Label>
            <div className='col-sm-10'>
            <Datetime dateFormat='YYYY-MM-DD' isValiDate={valid} name="m_start" onChange={handleStart}/>
            </div>
          </Form.Group>
          <Form.Group className="mb-3 row" controlId="edit-end">
            <Form.Label className="col-sm-2 col-form-label">끝</Form.Label>
            <div className='col-sm-10'>
              {/* 페이지 이동 처리? onChange로 하려고 datetime 씀? 이종간이다...*/}
            <Datetime dateFormat='YYYY-MM-DD' isValiDate={valid}  name="m_end" onChange={handleEnd}/>
            </div>
          </Form.Group>
          <Form.Group className="mb-3 row" controlId="boardContent">
            <Form.Label className="col-sm-2 col-form-label">내용</Form.Label>
            <div className='col-sm-10'>
            <textarea className="form-control" name='m_content' onChange={handleChangeForm} rows="3"></textarea>
            </div>
          </Form.Group>
        </Form>
        </Modal.Body>
        <Modal.Footer>
          <Button variant="secondary" onClick={handleClose}>
            닫기
          </Button>
          <Button variant="primary" onClick={memoAdd}>
            저장
          </Button>
        </Modal.Footer>
      </Modal>     
    </>
  )
}

export default SchedulePage

댓글