Ai-Mee Help Centre
Home
Features
How-To Guides
FAQ
Need Help?
Home
Features
How-To Guides
FAQ
Need Help?

Step 6 — Frontend: Types, Store, Shared Components

Files:

  • front-end/src/types/posts.ts
  • front-end/src/stores/posts.ts
  • front-end/src/components/partials/lifestyle/LifestyleContentTab.vue
  • front-end/src/components/pages/campaign/CampaignPosts.vue
  • front-end/src/components/partials/posts/PostDetailModal.vue

Prerequisites: Step 1 — DB Migration applied


What This Does

Removes all scheduled / scheduledDate references from shared frontend types, the posts store, and three components. After this step, nothing in the frontend reads or writes customer_posts.scheduled.


6.1 — front-end/src/types/posts.ts

Remove scheduled: string from the Post type and scheduledDate: Date | null from PostData.

Find:

export type Post = {
  id: number
  title: string
  html: string
  platforms: string[]
  scheduled: string
  status: 'new' | 'approved' | 'draft' | 'removed' | 'sent'

Replace with:

export type Post = {
  id: number
  title: string
  html: string
  platforms: string[]
  status: 'new' | 'approved' | 'draft' | 'removed' | 'sent'

Find and remove the scheduledDate field from PostData:

export interface PostData {
  scheduledDate: Date | null
  status: string
  title: string
}

Replace with:

export interface PostData {
  status: string
  title: string
}

6.2 — front-end/src/stores/posts.ts

Remove scheduled from the POST_CANONICAL_SELECT constant.

Find:

const POST_CANONICAL_SELECT = `
  id, title, platforms, scheduled, sent_at, status, created_at, updated_at,
  prompt, active, customer_id, campaign_id, email_list_id, generation_reason,
  customer:customer_customer(id, name),
  campaign:customer_campaign(id, name, customer_id)
`

Replace with:

const POST_CANONICAL_SELECT = `
  id, title, platforms, sent_at, status, created_at, updated_at,
  prompt, active, customer_id, campaign_id, email_list_id, generation_reason,
  customer:customer_customer(id, name),
  campaign:customer_campaign(id, name, customer_id)
`

6.3 — front-end/src/components/partials/lifestyle/LifestyleContentTab.vue

a) Fix postsByDate computed (line ~54) — remove post.scheduled from the date reference:

Find:

const ref = post.sent_at || post.scheduled || post.created_at

Replace with:

const ref = post.sent_at || post.created_at

b) Fix dayOfWeekCounts computed (line ~70) — remove p.scheduled:

Find:

const ref = p.sent_at || p.scheduled

Replace with:

const ref = p.sent_at

c) Fix the footer line referencing sent/scheduled count (line ~345):

Find:

        {{ posts.filter((p) => p.sent_at || p.scheduled).length }}
        scheduled/sent posts

Replace with:

        {{ posts.filter((p) => p.sent_at).length }}
        sent posts

d) Remove the scheduled column from columns (line ~133):

Find:

    {
      key: 'scheduled',
      label: 'Scheduled',
      sortable: true,
      colClass: 'hidden md:table-cell',
    },

Delete this entire object from the columns array.

e) Remove #cell-scheduled template slot (lines ~519-521):

Find and delete:

<template #cell-scheduled="{ row }">
  <span v-if="row.scheduled" class="text-muted-foreground">
    {{ dayjs(row.scheduled).format('MMM D, YYYY h:mm A') }}
  </span>
  <span v-else class="text-muted-foreground">—</span>
</template>

f) Remove scheduled from the Supabase select query (line ~187):

Find:

;`id, title, html, platforms, scheduled, sent_at, status, created_at, updated_at, prompt, active, generation_reason, context_sources`

Replace with:

;`id, title, html, platforms, sent_at, status, created_at, updated_at, prompt, active, generation_reason, context_sources`

6.4 — front-end/src/components/pages/campaign/CampaignPosts.vue

a) Remove scheduled column from columns array:

Find:

    { key: 'scheduled', label: 'Scheduled', sortable: true, colClass: 'hidden md:table-cell' },

Delete this line.

b) Remove #cell-scheduled template slot:

Find and delete:

<template #cell-scheduled="{ row }">
  {{ row.scheduled ? new Date(row.scheduled).toLocaleString() : 'Not Scheduled' }}
</template>

c) Fix the status cell that checks row.scheduled:

Find:

{{ _.startCase(row.scheduled && row.status === 'approved' ? 'scheduled' : row.status) }}

Replace with:

{{ _.startCase(row.status) }}

6.5 — front-end/src/components/partials/posts/PostDetailModal.vue

This has the most changes. Work through them carefully.

a) Remove scheduled?: string from the Post interface (line ~22):

Find:

  interface Post {
    id: number
    title: string
    platforms: string[]
    scheduled?: string
    status:

Replace with:

  interface Post {
    id: number
    title: string
    platforms: string[]
    status:

b) Remove scheduled?: string from the PostContent interface (line ~61):

Find:

    title?: string
    subtitle?: string | null
    platforms?: string[]
    scheduled?: string
    status?: string

Replace with:

    title?: string
    subtitle?: string | null
    platforms?: string[]
    status?: string

c) Remove scheduledDate: null from viewPostData initial value (line ~99):

Find:

const viewPostData = ref<any>({
  scheduledDate: null,
  status: 'new',
  title: '',
  active: true,
})

Replace with:

const viewPostData = ref<any>({
  status: 'new',
  title: '',
  active: true,
})

d) Remove 'scheduled' from viewStatusOptions (line ~109):

Find:

  const viewStatusOptions = [
    'new',
    'pending_review',
    'revision_requested',
    'approved',
    'scheduled',
    'sent',

Replace with:

  const viewStatusOptions = [
    'new',
    'pending_review',
    'revision_requested',
    'approved',
    'sent',

e) Replace the savePost logic that enforces the scheduled/date invariant (lines ~510-522):

Find:

const { title } = viewPostData.value
let { status, scheduledDate } = viewPostData.value

// Enforce status ↔ scheduled-date invariant at save time:
// • status !== 'scheduled' → clear any stale date (status wins)
// • status === 'scheduled' with no date → revert to 'approved'
if (status !== 'scheduled') {
  scheduledDate = null
} else if (!scheduledDate) {
  // 'scheduled' without a date is invalid — revert to approved
  status = 'approved'
}

const updates: Record<string, unknown> = { scheduled: scheduledDate, status, title }

Replace with:

const { title, status } = viewPostData.value
const updates: Record<string, unknown> = { status, title }

f) Remove scheduledDate assignment in openPostModal (line ~837):

Find:

viewPostData.value.scheduledDate = post.scheduled ? new Date(post.scheduled) : null
viewPostData.value.status = post.status

Replace with:

viewPostData.value.status = post.status

g) Remove scheduledDate: null from closePostModal reset (line ~880):

Find:

viewPostData.value = {
  scheduledDate: null,
  status: 'new',
  title: '',
  active: true,
}

Replace with:

viewPostData.value = {
  status: 'new',
  title: '',
  active: true,
}

h) Delete the watch that auto-promotes status when scheduledDate changes (line ~958):

Find and delete:

// When the user picks a scheduled date, auto-promote status to 'scheduled'
// so the save-time invariant (status !== 'scheduled' → clear date) doesn't drop it.
watch(
  () => viewPostData.value.scheduledDate,
  (newDate) => {
    if (newDate && viewPostData.value.status !== 'scheduled') {
      viewPostData.value.status = 'scheduled'
    }
  }
)

i) Check if there is a date-picker UI element in the template for scheduledDate — search the template section for scheduledDate and delete any date-picker input or v-model="viewPostData.scheduledDate" binding if present.


6.6 — Verify

cd front-end
pnpm test:tsc
# Should report 0 errors related to `scheduled` or `scheduledDate`

pnpm test:unit

✅ Done

Proceed to Step 7 — ClientOverview Calendar.