दस्तावेज़ीकरण — यह कैसे काम करता है
अंतिम अपडेट: 6 अगस्त 2026
1. प्रवाह अवलोकन
एक अपॉइंटमेंट साइन-इन किए गए आयोजक द्वारा बनाया जाता है, फिर एक यूनीक पब्लिक लिंक के ज़रिए किसी अतिथि को भेजा जाता है। अतिथि को किसी खाते की ज़रूरत नहीं: वह एक पब्लिक पेज से जवाब देता है, और जवाब तुरंत आयोजक के डैशबोर्ड पर दिखता है।
आयोजक (साइन-इन)
└─ एक अपॉइंटमेंट बनाता है ──▶ appointments (status = pending, invite_token जनरेट किया गया)
├─ «ईमेल से भेजें» ──▶ सर्वर फ़ंक्शन sendInviteEmail ──▶ Resend
└─ «लिंक कॉपी करें» ──▶ /invite/<token>
अतिथि (बिना खाते के)
└─ /invite/<token> खोलता है ──▶ RPC get_invite(_token) (फ़िल्टर की गई पब्लिक रीडिंग)
└─ स्वीकार / अस्वीकार ──▶ RPC respond_to_invite(_token, _accept, _message)
└─ status = accepted | declined, responded_at = now()
आयोजक
└─ डैशबोर्ड: स्थिति बैज, जवाब तिथि, अतिथि का संदेश, आंकड़े2. आमंत्रण ईमेल की सामग्री
ईमेल सर्वर साइड पर sendInviteEmail फ़ंक्शन में तैयार किया जाता है और Resend के ज़रिए भेजा जाता है। प्रेषक: RESEND_FROM का मान (डिफ़ॉल्ट «Cadence <onboarding@resend.dev>»)। विषय: «अपॉइंटमेंट: {{title}}».
बॉडी संरचना, क्रम में:
- शीर्षक «अपॉइंटमेंट प्रस्ताव»।
- अभिवादन «नमस्ते {{guestName}},»।
- व्यक्तिगत संदेश ब्लॉक (केवल Business आयोजकों के लिए)।
- बोल्ड में अपॉइंटमेंट शीर्षक, फिर भाषा के अनुसार फ़ॉर्मेट की गई तारीख और समय स्लॉट।
- स्थान और विवरण, प्रत्येक तभी दिखता है जब भरा गया हो।
- आमंत्रण लिंक की ओर इशारा करता हरा एक्शन बटन «पुष्टि करें या अस्वीकार करें»।
- बटन ब्लॉक करने वाले मेल क्लाइंट्स के लिए प्लेन टेक्स्ट में लिंक रिमाइंडर।
- «Google समीक्षाएं» ब्लॉक (Business): व्यवसाय का नाम, रेटिंग, समीक्षा लिंक, Maps लिंक।
सभी डायनामिक मान इंसर्ट करने से पहले HTML-एस्केप किए जाते हैं: आयोजक द्वारा दर्ज की गई कोई भी सामग्री ईमेल में मार्कअप इंजेक्ट नहीं कर सकती।
उपलब्ध वेरिएबल
| वेरिएबल | स्रोत | उपयोग |
|---|---|---|
| {{guestName}} | contacts.name | अभिवादन पंक्ति «नमस्ते {{guestName}},»। यदि कोई संपर्क जुड़ा नहीं है तो खाली। |
| {{title}} | appointments.title | ईमेल विषय «अपॉइंटमेंट: {{title}}» और बॉडी में बोल्ड शीर्षक। |
| {{dateRange}} | appointments.starts_at / ends_at | भाषा के अनुसार फ़ॉर्मेट किया गया: «मंगलवार, 12 अगस्त, 15:00 → 15:30» (Intl.DateTimeFormat)। |
| {{location}} | appointments.location | पंक्ति «स्थान: …»। यदि फ़ील्ड खाली है तो पूरा ब्लॉक छोड़ दिया जाता है। |
| {{description}} | appointments.description | तारीख के नीचे दिखने वाला फ्री-टेक्स्ट पैराग्राफ़। खाली होने पर छोड़ दिया जाता है। |
| {{inviteLink}} | origin + /invite/ + appointments.invite_token | «पुष्टि करें या अस्वीकार करें» बटन + ईमेल के नीचे प्लेन टेक्स्ट में लिंक रिमाइंडर (कॉपी/पेस्ट के लिए)। |
| {{inviteMessage}} | profiles.invite_message (Business) | व्यक्तिगत संदेश का हरा बॉक्स, केवल Business आयोजक के लिए दिखता है। |
| {{businessName}} / {{googleRating}} / {{googleReviewUrl}} / {{googleMapsUrl}} | profiles.* (Business) | यदि यह विकल्प सक्रिय है, तो ईमेल फ़ुटर और आमंत्रण पेज पर «Google समीक्षाएं» ब्लॉक। |
वे मामले जहां भेजना पूरा नहीं होता
- no_email : संपर्क के पास ईमेल पता नहीं है। आयोजक को लिंक कॉपी करके किसी अन्य माध्यम से भेजना होगा।
- no_api_key : भेजने की कुंजी कॉन्फ़िगर नहीं है। मैन्युअल कॉपी के लिए आमंत्रण लिंक फिर भी इंटरफ़ेस पर लौटाया जाता है।
- provider_error : ईमेल प्रोवाइडर द्वारा अस्वीकृति (अमान्य पता, असत्यापित डोमेन…)। अपॉइंटमेंट की स्थिति अपरिवर्तित रहती है।
- सफल होने पर, invite_sent_at को टाइमस्टैंप किया जाता है: यह फ़ील्ड आंकड़ों में «भेजे गए लिंक» की ट्रैकिंग को फ़ीड करता है।
3. पुष्टि स्क्रीन (पेज /invite/<token>)
बिना प्रमाणीकरण वाला पब्लिक पेज, सुरक्षित फ़ंक्शन get_invite से रेंडर किया गया, जो केवल डिस्प्ले के लिए आवश्यक फ़ील्ड लौटाता है।
- लोड हो रहा है : जवाब आने तक एनिमेटेड स्केलेटन (कैलेंडर)।
- अमान्य या समाप्त लिंक : एरर मैसेज; आयोजक या अपॉइंटमेंट के बारे में कोई जानकारी उजागर नहीं की जाती।
- «लंबित» स्थिति : विषय, तारीख और समय स्लॉट, अवधि, स्थान, आयोजक का नाम, व्यक्तिगत संदेश (Business), वैकल्पिक फ्री-टेक्स्ट फ़ील्ड (अधिकतम 500 वर्ण), फिर दो बटन «मैं स्वीकार करता/करती हूँ» और «मैं अस्वीकार करता/करती हूँ»।
- स्वीकृति के बाद : हरा «स्वीकृत» बैज, स्क्रीन पर पुष्टि, व्यावहारिक जानकारी का रिमाइंडर, और यदि आयोजक Business पर है तो Google समीक्षा ब्लॉक।
- अस्वीकृति के बाद : लाल «अस्वीकृत» बैज, यह बताता संदेश कि आयोजक को सूचित कर दिया गया है; जब तक अपॉइंटमेंट रद्द नहीं होता, अतिथि लिंक फिर से खोलकर अपना जवाब बदल सकता है।
- रद्द किया गया अपॉइंटमेंट : जवाब बटन का अब कोई असर नहीं रहता, दिखाई जाने वाली स्थिति «रद्द» ही रहती है।
अतिथि द्वारा दर्ज किया गया फ्री-टेक्स्ट संदेश क्लाइंट साइड पर 500 वर्ण और डेटाबेस साइड पर 1000 वर्ण तक सीमित किया जाता है, फिर आयोजक को अपॉइंटमेंट रिकॉर्ड पर दिखाया जाता है।
4. अपॉइंटमेंट की स्थितियां
| स्थिति | लेबल | ट्रिगर | प्रभाव |
|---|---|---|---|
| pending | लंबित | अपॉइंटमेंट बनाते समय (डेटाबेस में डिफ़ॉल्ट मान)। | लिंक सक्रिय है, अतिथि जवाब दे सकता है। «अपेक्षित जवाब» में गिना जाता है। |
| accepted | स्वीकृत | अतिथि «स्वीकार करता हूँ» पर क्लिक करता है — respond_to_invite(_accept = true) कॉल होता है। | responded_at और response_message भरे जाते हैं; डैशबोर्ड पर हरा बैज। |
| declined | अस्वीकृत | अतिथि «अस्वीकार करता हूँ» पर क्लिक करता है — respond_to_invite(_accept = false)। | स्वीकृति जैसा ही रिकॉर्ड, लाल बैज। स्लॉट फ़ॉलो-अप के लिए दृश्यमान रहता है। |
| cancelled | रद्द | आयोजक द्वारा अपने डैशबोर्ड से की गई कार्रवाई। | लिंक अब कोई जवाब स्वीकार नहीं करता (respond_to_invite केवल अन्य स्थितियों को अपडेट करता है)। |
5. सर्वर-साइड प्रवाह
- बनाना / संपादित करना / हटाना : प्रमाणित क्लाइंट द्वारा किया जाता है; डेटा आइसोलेशन डेटाबेस एक्सेस नियमों द्वारा सुनिश्चित किया जाता है।
- sendInviteEmail: एक सुरक्षित सर्वर फ़ंक्शन। यह अनुरोधकर्ता की ID के आधार पर फ़िल्टर करके अपॉइंटमेंट को फिर से लोड करता है, यदि अपॉइंटमेंट उसका नहीं है तो मना करता है, ईमेल तैयार करता है, Resend को कॉल करता है और फिर भेजने को टाइमस्टैंप करता है।
- get_invite(_token): उच्च विशेषाधिकार वाला डेटाबेस फ़ंक्शन, पब्लिक रीडिंग का एकमात्र रास्ता। यह केवल डिस्प्ले फ़ील्ड लौटाता है और गैर-Business आयोजक के लिए ब्रांडिंग जानकारी छुपाता है।
- respond_to_invite(_token, _accept, _message): स्थिति, संदेश और जवाब टाइमस्टैंप अपडेट करता है। यह केवल टोकन से मेल खाती पंक्ति पर काम करता है और रद्द किए गए अपॉइंटमेंट को अनदेखा करता है।
- get_plan_usage(): कोटा प्रदर्शित करने के लिए प्लान, माह की खपत और एडमिन इंडिकेटर लौटाता है।
6. प्राधिकरण तर्क
- आयोजक : केवल अपने संपर्कों और अपॉइंटमेंट्स तक पूर्ण रीड/राइट एक्सेस।
- साइन-इन न किया गया अतिथि : टेबल तक कोई सीधी पहुंच नहीं। वह केवल अपने टोकन के ज़रिए एक अपॉइंटमेंट पढ़ सकता है और उसका जवाब दे सकता है। टोकन रैंडम है (36 हेक्साडेसिमल वर्ण) और इसके अलावा किसी और चीज़ तक पहुंच नहीं देता।
- भूमिकाएं : एक समर्पित टेबल में संग्रहीत (उपयोगकर्ता, मॉडरेटर, एडमिन) और सर्वर साइड पर सत्यापित; अधिकार देने के लिए इन्हें कभी भी ब्राउज़र से नहीं पढ़ा जाता।
- एडमिन : /admin क्षेत्र तक पहुंच (सभी खाते, संपर्क और अपॉइंटमेंट) और Free-mium प्लान के कोटा से छूट।
- प्लान : स्तर परिवर्तन क्लाइंट से जबरन नहीं किया जा सकता; केवल Stripe भुगतान प्रक्रिया या कोई एडमिन इसे बदल सकते हैं।
- कोटा : हर निर्माण से पहले डेटाबेस साइड पर लागू — प्रति कैलेंडर माह 10/15 (Free-mium), 30/50 (Basic), 50/100 (Standard), 250/500 (Economic) संपर्क/अपॉइंटमेंट, Business और एडमिन के लिए असीमित।
7. संपादकीय टीम के लिए चेकलिस्ट
- ईमेल टेक्स्ट बदलना: भेजने वाले फ़ंक्शन के HTML टेम्पलेट पर काम करें, आमंत्रण पेज पर नहीं।
- पुष्टि स्क्रीन बदलना: पब्लिक आमंत्रण पेज पर काम करें।
- किसी भी नए वेरिएबल का स्रोत पब्लिक रीड फ़ंक्शन द्वारा पहले से उजागर की गई फ़ील्ड होनी चाहिए।
- पब्लिक पेज पर कभी भी किसी अन्य अपॉइंटमेंट या संपर्क का डेटा न दिखाएं।
- हमेशा तीनों स्थितियों का परीक्षण करें: लंबित, स्वीकृत, अस्वीकृत।