Calendar
This demo shows the real-time collaborative version of a Calendar with Yorkie and Next.js.
page.tsx
1/**2 * yorkie-js-sdk must be loaded on client-side3 */4'use client';56import styles from './styles/page.module.css';7import React, { useEffect, useState } from 'react';89import { ContentTypes, ENVtypes } from './utils/types';10import { displayPeers, createRandomPeers } from './utils/handlePeers';11import { parseDate } from './utils/parseDate';12import yorkie, { Document, JSONArray, DocEventType } from 'yorkie-js-sdk';13import Scheduler from './Scheduler';1415// parseDate() value's format = "DD-MM-YYYY"16const defaultContent: JSONArray<ContentTypes> = [17 {18 date: parseDate(new Date()).replace(/^\d{2}/, '01'),19 text: 'payday',20 },21 {22 date: parseDate(new Date()).replace(/^\d{2}/, '17'),23 text: "Garry's birthday",24 },25];2627const ENV: ENVtypes = {28 url: process.env.NEXT_PUBLIC_YORKIE_API_ADDR!,29 apiKey: process.env.NEXT_PUBLIC_YORKIE_API_KEY!,30};3132const documentKey = `next.js-Scheduler-${parseDate(new Date())}`;3334/**35 * main page36 */37export default function Editor() {38 const [peers, setPeers] = useState<Array<string>>([]);39 const [content, setContent] = useState<Array<ContentTypes>>(defaultContent);4041 // create Yorkie Document with useState value42 const [doc] = useState<Document<{ content: JSONArray<ContentTypes> }>>(43 () =>44 new yorkie.Document<{ content: JSONArray<ContentTypes> }>(documentKey),45 );4647 const actions = {48 // push new content to Yorkie's database49 addContent(date: string, text: string) {50 doc.update((root) => {51 root.content.push({ date, text });52 });53 },5455 // delete selected content at Yorkie's database56 deleteContent(date: string) {57 doc.update((root) => {58 let target;59 for (const item of root.content) {60 if (item.date === date) {61 target = item as any;62 break;63 }64 }6566 if (target) {67 root.content.deleteByID!(target.getID());68 }69 });70 },7172 // edit selected content at Yorkie's database73 updateContent(date: string, text: string) {74 doc.update((root) => {75 let target;76 for (const item of root.content) {77 if (item.date === date) {78 target = item;79 break;80 }81 }8283 if (target) {84 target.text = text;85 }86 });87 },88 };8990 useEffect(() => {91 // create Yorkie Client at client-side92 const client = new yorkie.Client(ENV.url, {93 apiKey: ENV.apiKey,94 });9596 // subscribe document event of "PresenceChanged"(="peers-changed")97 doc.subscribe('presence', (event) => {98 if (event.type !== DocEventType.PresenceChanged) {99 setPeers(displayPeers(doc.getPresences()));100 }101 });102103 /**104 * `attachDoc` is a helper function to attach the document into the client.105 */106 async function attachDoc(107 doc: Document<{ content: JSONArray<ContentTypes> }>,108 callback: (props: any) => void,109 ) {110 // 01. activate client111 await client.activate();112 // 02. attach the document into the client with presence113 await client.attach(doc, {114 initialPresence: {115 userName: createRandomPeers(),116 },117 });118119 // 03. create default content if not exists.120 doc.update((root) => {121 if (!root.content) {122 root.content = defaultContent;123 }124 }, 'create default content if not exists');125126 // 04. subscribe doc's change event from local and remote.127 doc.subscribe(() => {128 callback(doc.getRoot().content);129 });130131 // 05. set content to the attached document.132 callback(doc.getRoot().content);133 }134135 attachDoc(doc, (content) => setContent(content));136 }, []);137138 return (139 <main className={styles.main}>140 <p>141 peers : [142 {peers.map((man: string, i: number) => {143 return <span key={i}> {man}, </span>;144 })}{' '}145 ]146 </p>147 <Scheduler content={content} actions={actions} />148 </main>149 );150}
- User 1
- User 2
- User 1
- User 2
Event Log