diff --git a/actions/cancelScheduledPost.ts b/actions/cancelScheduledPost.ts
index 273545f2..47ce32b0 100644
--- a/actions/cancelScheduledPost.ts
+++ b/actions/cancelScheduledPost.ts
@@ -16,6 +16,10 @@ export async function cancelScheduledPost(args: {
let identity = await getIdentityData();
if (!identity || !identity.atp_did) return Err({ type: "not_authenticated" });
+ if (!identity.entitlements?.can_schedule_posts) {
+ return Err({ type: "not_found" });
+ }
+
if (args.publication_uri) {
const { data: pub } = await supabaseServerClient
.from("publications")
diff --git a/actions/schedulePost.ts b/actions/schedulePost.ts
index 87001181..a5e9f4a0 100644
--- a/actions/schedulePost.ts
+++ b/actions/schedulePost.ts
@@ -39,6 +39,10 @@ export async function schedulePost(args: {
let identity = await getIdentityData();
if (!identity || !identity.atp_did) return Err({ type: "not_authenticated" });
+ if (!identity.entitlements?.can_schedule_posts) {
+ return Err({ type: "not_found" });
+ }
+
if (!identity.entitlements?.publication_analytics) {
return Err({ type: "not_pro" });
}
@@ -85,13 +89,17 @@ export async function schedulePost(args: {
);
if (!found) return Err({ type: "not_found" });
- await inngest.send({
- name: "post/scheduled-publish",
- data: {
- leaflet_id: args.leaflet_id,
- publication_uri: args.publication_uri,
- },
- });
+ try {
+ await inngest.send({
+ name: "post/scheduled-publish",
+ data: {
+ leaflet_id: args.leaflet_id,
+ publication_uri: args.publication_uri,
+ },
+ });
+ } catch (e) {
+ console.log(e);
+ }
return Ok({ scheduled_publish_at: scheduledAt.toISOString() });
}
diff --git a/app/(home-pages)/home/LeafletList/LeafletInfo.tsx b/app/(home-pages)/home/LeafletList/LeafletInfo.tsx
index f2fb11de..ef5bd491 100644
--- a/app/(home-pages)/home/LeafletList/LeafletInfo.tsx
+++ b/app/(home-pages)/home/LeafletList/LeafletInfo.tsx
@@ -11,6 +11,7 @@ import {
SCHEDULED_DATE_FORMAT,
getFutureScheduledAt,
} from "src/utils/scheduledPublish";
+import { useCanSchedulePosts } from "src/hooks/useEntitlement";
export const LeafletInfo = (props: {
title?: string;
@@ -21,6 +22,7 @@ export const LeafletInfo = (props: {
loggedIn: boolean;
}) => {
const pubStatus = useLeafletPublicationStatus();
+ const canSchedule = useCanSchedulePosts();
let prettyCreatedAt = props.added_at ? timeAgo(props.added_at) : "";
let prettyPublishedAt = pubStatus?.publishedAt
? timeAgo(pubStatus.publishedAt)
@@ -44,7 +46,9 @@ export const LeafletInfo = (props: {
{title}
- {scheduledFor && }
+ {scheduledFor && canSchedule && (
+
+ )}
diff --git a/app/[leaflet_id]/actions/PublishButton.tsx b/app/[leaflet_id]/actions/PublishButton.tsx
index 14fde8a2..1a859ca8 100644
--- a/app/[leaflet_id]/actions/PublishButton.tsx
+++ b/app/[leaflet_id]/actions/PublishButton.tsx
@@ -33,6 +33,7 @@ import { normalizePublicationRecord } from "src/utils/normalizeRecords";
import { useParams, useRouter, useSearchParams } from "next/navigation";
import { useState, useMemo, useEffect } from "react";
import { useIsMobile } from "src/hooks/isMobile";
+import { useCanSchedulePosts } from "src/hooks/useEntitlement";
import { useReplicache, useEntity } from "src/replicache";
import { useSubscribe } from "src/replicache/useSubscribe";
import { Json } from "supabase/database.types";
@@ -54,12 +55,13 @@ export const PublishButton = (props: { entityID: string }) => {
let { permission_token } = useReplicache();
let params = useParams();
let router = useRouter();
+ const canSchedule = useCanSchedulePosts();
if (!pub) return ;
const scheduledFor = getFutureScheduledAt(pub.scheduled_publish_at);
- if (scheduledFor) {
+ if (scheduledFor && canSchedule) {
return (
{
const isPro = useIsPro();
+ const canSchedule = useCanSchedulePosts();
const [showUpgradeModal, setShowUpgradeModal] = useState(false);
let editorStateRef = useRef(null);
let [state, setState] = useState<"post-details" | "share-options">(
@@ -286,6 +287,7 @@ const PublishPostForm = (
@@ -538,6 +540,7 @@ const PublicationSocialPreview = (props: {
const DateOptions = (props: {
publishedAt: Date | undefined;
setPublishedAt: (date: Date | undefined) => void;
+ canSchedule: boolean;
}) => {
const formattedDate = useLocalizedDate(
props.publishedAt?.toISOString() || "",
@@ -549,13 +552,24 @@ const DateOptions = (props: {
return `${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}`;
});
+ const clampToNow = (date: Date): { date: Date; time: string } => {
+ const now = new Date();
+ if (!props.canSchedule && date > now) {
+ const time = `${now.getHours().toString().padStart(2, "0")}:${now.getMinutes().toString().padStart(2, "0")}`;
+ return { date: now, time };
+ }
+ return { date, time: timeValue };
+ };
+
const handleTimeChange = (time: string) => {
setTimeValue(time);
if (!props.publishedAt) return;
const [hours, minutes] = time.split(":").map((str) => parseInt(str, 10));
const newDate = setHours(setMinutes(props.publishedAt, minutes), hours);
- props.setPublishedAt(newDate);
+ const clamped = clampToNow(newDate);
+ setTimeValue(clamped.time);
+ props.setPublishedAt(clamped.date);
};
const handleDateChange = (date: Date | undefined) => {
@@ -573,7 +587,9 @@ const DateOptions = (props: {
hours,
minutes,
);
- props.setPublishedAt(newDate);
+ const clamped = clampToNow(newDate);
+ setTimeValue(clamped.time);
+ props.setPublishedAt(clamped.date);
};
const scheduled = !!props.publishedAt && isFuture(props.publishedAt);
@@ -600,6 +616,11 @@ const DateOptions = (props: {
mode="single"
selected={props.publishedAt}
onSelect={handleDateChange}
+ disabled={
+ props.canSchedule
+ ? undefined
+ : (date: Date) => date > new Date()
+ }
/>
diff --git a/app/api/rpc/[command]/get_publication_data.ts b/app/api/rpc/[command]/get_publication_data.ts
index 714ad992..6f0401ae 100644
--- a/app/api/rpc/[command]/get_publication_data.ts
+++ b/app/api/rpc/[command]/get_publication_data.ts
@@ -64,6 +64,7 @@ export const get_publication_data = makeRoute({
.limit(1)
.single();
+ console.log(error);
let leaflet_data = await getFactsFromHomeLeaflets.handler(
{
tokens:
diff --git a/src/hooks/useEntitlement.ts b/src/hooks/useEntitlement.ts
index 9f62c33e..e9c1683b 100644
--- a/src/hooks/useEntitlement.ts
+++ b/src/hooks/useEntitlement.ts
@@ -17,3 +17,7 @@ export function useCanSeePro(): boolean {
export function useCanSeeNewsletterMode(): boolean {
return useHasEntitlement("can_see_newsletter_mode");
}
+
+export function useCanSchedulePosts(): boolean {
+ return useHasEntitlement("can_schedule_posts");
+}