Skip to content

Commit 4644271

Browse files
committed
feat(booking,passionfroot,ops): hard-block calendar holds, StreamYard & 15m Google Meet pre-calls, Sanity Media Library vault, and Passionfroot Creator API bridge
1 parent 8cea81b commit 4644271

12 files changed

Lines changed: 5122 additions & 452 deletions

File tree

‎apps/ops/src/App.tsx‎

Lines changed: 1648 additions & 218 deletions
Large diffs are not rendered by default.

‎apps/sanity/extract.json‎

Lines changed: 558 additions & 0 deletions
Large diffs are not rendered by default.

‎apps/sanity/schemas/documents/booking.ts‎

Lines changed: 137 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,31 @@ export default defineType({
2929
title: 'Social Handle or Portfolio URL',
3030
type: 'url',
3131
}),
32+
defineField({
33+
name: 'bookingSource',
34+
title: 'Booking Source',
35+
type: 'string',
36+
options: {
37+
list: [
38+
{title: 'Direct Book (codingcat.dev/book)', value: 'direct'},
39+
{title: 'Passionfroot Creator API', value: 'passionfroot'},
40+
],
41+
},
42+
initialValue: 'direct',
43+
}),
44+
defineField({
45+
name: 'sessionType',
46+
title: 'Session Type',
47+
type: 'string',
48+
options: {
49+
list: [
50+
{title: '45m Recording Session', value: 'recording-45m'},
51+
{title: '15m Pre-Meeting Only (Google Meet)', value: 'pre-meeting-15m'},
52+
{title: '45m Recording + 15m Google Meet Pre-Meeting', value: 'recording-with-pre-meeting'},
53+
],
54+
},
55+
initialValue: 'recording-45m',
56+
}),
3257
defineField({
3358
name: 'track',
3459
title: 'Booking Track',
@@ -38,6 +63,7 @@ export default defineType({
3863
{title: 'Editorial Guest Application (Free / Review Queue)', value: 'editorial'},
3964
{title: 'Sponsored Podcast & Multi-Channel Showcase ($2,000 Fast-Track)', value: 'sponsored'},
4065
{title: 'Full-Stack Launch Bundle ($3,500 Kickoff & Demo)', value: 'full-stack-launch'},
66+
{title: '15m Pre-Meeting / Sponsor Kickoff (Google Meet)', value: 'sponsor-kickoff'},
4167
],
4268
},
4369
initialValue: 'editorial',
@@ -49,9 +75,10 @@ export default defineType({
4975
type: 'string',
5076
options: {
5177
list: [
52-
{title: 'Pending Review / Deposit', value: 'pending'},
53-
{title: 'Approved / Deposit Paid', value: 'approved'},
78+
{title: 'Pending Review / Calendar Hold (Opaque Busy)', value: 'pending'},
79+
{title: 'Approved (StreamYard Sent)', value: 'approved'},
5480
{title: 'Scheduled on Google Calendar', value: 'scheduled'},
81+
{title: 'Confirmed', value: 'confirmed'},
5582
{title: 'Recorded', value: 'recorded'},
5683
{title: 'Published', value: 'published'},
5784
{title: 'Declined / Cancelled', value: 'cancelled'},
@@ -64,6 +91,42 @@ export default defineType({
6491
title: 'Requested Recording Slot (UTC ISO)',
6592
type: 'datetime',
6693
}),
94+
defineField({
95+
name: 'recordingUrl',
96+
title: 'Recording Studio URL (StreamYard)',
97+
type: 'url',
98+
initialValue: 'https://streamyard.com/c4kv26is93',
99+
}),
100+
defineField({
101+
name: 'preMeetingStatus',
102+
title: 'Pre-Meeting Status (15m Google Meet)',
103+
type: 'string',
104+
options: {
105+
list: [
106+
{title: 'Not Needed', value: 'not_needed'},
107+
{title: 'Requested by Host / Guest', value: 'requested'},
108+
{title: 'Scheduled on Google Meet', value: 'scheduled'},
109+
{title: 'Completed', value: 'completed'},
110+
{title: 'Bypassed by Host', value: 'bypassed'},
111+
],
112+
},
113+
initialValue: 'not_needed',
114+
}),
115+
defineField({
116+
name: 'preMeetingSlotStartAt',
117+
title: '15m Pre-Meeting Slot (UTC ISO)',
118+
type: 'datetime',
119+
}),
120+
defineField({
121+
name: 'preMeetingGoogleEventId',
122+
title: 'Pre-Meeting Google Calendar Event ID',
123+
type: 'string',
124+
}),
125+
defineField({
126+
name: 'preMeetingMeetUrl',
127+
title: '15m Pre-Meeting Google Meet URL',
128+
type: 'url',
129+
}),
67130
defineField({
68131
name: 'topics',
69132
title: 'Proposed Topics & Key Talking Points',
@@ -130,6 +193,78 @@ export default defineType({
130193
type: 'reference',
131194
to: [{type: 'sponsorLead'}],
132195
}),
196+
defineField({
197+
name: 'passionfrootCollaborationId',
198+
title: 'Passionfroot Collaboration ID',
199+
type: 'string',
200+
}),
201+
defineField({
202+
name: 'passionfrootPlacementId',
203+
title: 'Passionfroot Placement ID',
204+
type: 'string',
205+
}),
206+
defineField({
207+
name: 'passionfrootConversationId',
208+
title: 'Passionfroot Conversation ID',
209+
type: 'string',
210+
}),
211+
defineField({
212+
name: 'sharedAssets',
213+
title: 'Sanity Media Library Vault Assets',
214+
type: 'array',
215+
of: [
216+
{
217+
type: 'object',
218+
fields: [
219+
defineField({name: 'title', title: 'Asset Title / Filename', type: 'string'}),
220+
defineField({
221+
name: 'category',
222+
title: 'Category',
223+
type: 'string',
224+
options: {
225+
list: [
226+
{title: 'Brand Logo / SVG', value: 'logo'},
227+
{title: 'Talking Points / Brief', value: 'brief'},
228+
{title: 'Slide Deck / Demo Assets', value: 'slides'},
229+
{title: 'Contract / Legal', value: 'legal'},
230+
{title: 'Raw Audio / Video / B-Roll', value: 'media'},
231+
],
232+
},
233+
}),
234+
defineField({
235+
name: 'visibility',
236+
title: 'Visibility',
237+
type: 'string',
238+
options: {
239+
list: [
240+
{title: 'Private to Deal Room (Token-Gated)', value: 'private'},
241+
{title: 'Public Brand Asset', value: 'public'},
242+
],
243+
},
244+
initialValue: 'private',
245+
}),
246+
defineField({
247+
name: 'uploadedBy',
248+
title: 'Uploaded By',
249+
type: 'string',
250+
options: {
251+
list: [
252+
{title: 'Partner / Guest', value: 'partner'},
253+
{title: 'CodingCat.dev Studio', value: 'codingcat'},
254+
{title: 'Passionfroot Auto-Ingest', value: 'passionfroot'},
255+
],
256+
},
257+
initialValue: 'partner',
258+
}),
259+
defineField({name: 'uploadedAt', title: 'Uploaded At', type: 'datetime'}),
260+
defineField({name: 'assetId', title: 'Sanity Asset ID', type: 'string'}),
261+
defineField({name: 'mimeType', title: 'MIME Type', type: 'string'}),
262+
defineField({name: 'fileSize', title: 'File Size (Bytes)', type: 'number'}),
263+
defineField({name: 'externalUrl', title: 'Direct / Proxied URL', type: 'url'}),
264+
],
265+
},
266+
],
267+
}),
133268
],
134269
preview: {
135270
select: {

‎apps/sanity/schemas/documents/sponsorLead.ts‎

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,24 @@ export default defineType({
4444
{title: 'Inbound Website', value: 'inbound'},
4545
{title: 'Gmail Thread', value: 'gmail'},
4646
{title: 'Outbound Scraper', value: 'outbound'},
47-
{title: 'Fast-Track Booking', value: 'booking'},
47+
{title: 'Fast-Track Direct Booking', value: 'booking'},
48+
{title: 'Passionfroot Creator API', value: 'passionfroot'},
4849
],
4950
},
5051
validation: (Rule) => Rule.required(),
5152
}),
53+
defineField({
54+
name: 'billingProvider',
55+
title: 'Billing Provider',
56+
type: 'string',
57+
options: {
58+
list: [
59+
{title: 'CodingCat.dev Stripe (50% Deposit / 50% Balance)', value: 'stripe'},
60+
{title: 'Passionfroot Managed Billing', value: 'passionfroot'},
61+
],
62+
},
63+
initialValue: 'stripe',
64+
}),
5265
defineField({
5366
name: 'status',
5467
title: 'Status',
@@ -227,6 +240,140 @@ export default defineType({
227240
title: 'Notes',
228241
type: 'text',
229242
}),
243+
defineField({
244+
name: 'passionfrootPartnerId',
245+
title: 'Passionfroot Partner ID',
246+
type: 'string',
247+
}),
248+
defineField({
249+
name: 'passionfrootCollaborationId',
250+
title: 'Passionfroot Collaboration ID',
251+
type: 'string',
252+
}),
253+
defineField({
254+
name: 'passionfrootConversationId',
255+
title: 'Passionfroot Conversation ID',
256+
type: 'string',
257+
}),
258+
defineField({
259+
name: 'passionfrootRequestId',
260+
title: 'Passionfroot Active Request ID',
261+
type: 'string',
262+
}),
263+
defineField({
264+
name: 'passionfrootProposalId',
265+
title: 'Passionfroot Active Proposal ID',
266+
type: 'string',
267+
}),
268+
defineField({
269+
name: 'passionfrootProposalStatus',
270+
title: 'Passionfroot Proposal / Request Status',
271+
type: 'string',
272+
}),
273+
defineField({
274+
name: 'passionfrootNetEarningsCents',
275+
title: 'Passionfroot Net Creator Earnings (Cents)',
276+
type: 'number',
277+
description: 'Creator payout after Passionfroot fees and before taxes',
278+
}),
279+
defineField({
280+
name: 'passionfrootGrossBudgetCents',
281+
title: 'Passionfroot Disclosed Brand Gross Budget (Cents)',
282+
type: 'number',
283+
}),
284+
defineField({
285+
name: 'passionfrootCurrency',
286+
title: 'Passionfroot Currency',
287+
type: 'string',
288+
initialValue: 'USD',
289+
}),
290+
defineField({
291+
name: 'passionfrootUnread',
292+
title: 'Passionfroot Unread Messages',
293+
type: 'boolean',
294+
initialValue: false,
295+
}),
296+
defineField({
297+
name: 'passionfrootLastMessageAt',
298+
title: 'Passionfroot Last Message At',
299+
type: 'datetime',
300+
}),
301+
defineField({
302+
name: 'passionfrootMessages',
303+
title: 'Passionfroot Conversation Timeline',
304+
type: 'array',
305+
of: [
306+
{
307+
type: 'object',
308+
fields: [
309+
defineField({name: 'messageId', title: 'Message ID', type: 'string'}),
310+
defineField({name: 'senderType', title: 'Sender Type', type: 'string'}),
311+
defineField({name: 'itemType', title: 'Item Type', type: 'string'}),
312+
defineField({name: 'text', title: 'Message Text', type: 'text'}),
313+
defineField({name: 'createdAt', title: 'Created At', type: 'datetime'}),
314+
defineField({name: 'requestId', title: 'Request ID', type: 'string'}),
315+
defineField({name: 'proposalId', title: 'Proposal ID', type: 'string'}),
316+
],
317+
},
318+
],
319+
}),
320+
defineField({
321+
name: 'sharedAssets',
322+
title: 'Sanity Media Library Vault Assets',
323+
type: 'array',
324+
of: [
325+
{
326+
type: 'object',
327+
fields: [
328+
defineField({name: 'title', title: 'Asset Title / Filename', type: 'string'}),
329+
defineField({
330+
name: 'category',
331+
title: 'Category',
332+
type: 'string',
333+
options: {
334+
list: [
335+
{title: 'Brand Logo / SVG', value: 'logo'},
336+
{title: 'Talking Points / Brief', value: 'brief'},
337+
{title: 'Slide Deck / Demo Assets', value: 'slides'},
338+
{title: 'Contract / Legal', value: 'legal'},
339+
{title: 'Raw Audio / Video / B-Roll', value: 'media'},
340+
],
341+
},
342+
}),
343+
defineField({
344+
name: 'visibility',
345+
title: 'Visibility',
346+
type: 'string',
347+
options: {
348+
list: [
349+
{title: 'Private to Deal Room (Token-Gated)', value: 'private'},
350+
{title: 'Public Brand Asset', value: 'public'},
351+
],
352+
},
353+
initialValue: 'private',
354+
}),
355+
defineField({
356+
name: 'uploadedBy',
357+
title: 'Uploaded By',
358+
type: 'string',
359+
options: {
360+
list: [
361+
{title: 'Partner / Guest', value: 'partner'},
362+
{title: 'CodingCat.dev Studio', value: 'codingcat'},
363+
{title: 'Passionfroot Auto-Ingest', value: 'passionfroot'},
364+
],
365+
},
366+
initialValue: 'partner',
367+
}),
368+
defineField({name: 'uploadedAt', title: 'Uploaded At', type: 'datetime'}),
369+
defineField({name: 'assetId', title: 'Sanity Asset ID', type: 'string'}),
370+
defineField({name: 'mimeType', title: 'MIME Type', type: 'string'}),
371+
defineField({name: 'fileSize', title: 'File Size (Bytes)', type: 'number'}),
372+
defineField({name: 'externalUrl', title: 'Direct / Proxied URL', type: 'url'}),
373+
],
374+
},
375+
],
376+
}),
230377
],
231378
preview: {
232379
select: {

0 commit comments

Comments
 (0)