nyuchimzizi
Mzizi — an open-architecture project of the Bundu Foundation, operated and developed by Nyuchi. Built on the Five African Minerals palette.
Built by Nyuchi Africav4.0.39
Editorial calendar showing scheduled content across a week or month view. Drag-and-drop scheduling, content type color coding, and publish status indicators. Used in Mukoko News editorial management and Bytes creator scheduling.
View the full component source code below.
"use client"
import * as React from "react"
import { cn } from "@/lib/utils"
interface ContentItem {
id: string
title: string
type: string
status: "draft" | "scheduled" | "published"
date: string
color?: string
}
interface ContentCalendarProps extends React.ComponentProps<"div"> {
items: ContentItem[]
view?: "week" | "month"
onItemClick?: (id: string) => void
onDateClick?: (date: string) => void
}
const statusStyles = {
draft: "border-muted-foreground/30 bg-muted/30",
scheduled: "border-[var(--color-cobalt,#00B0FF)]/30 bg-[var(--color-cobalt,#00B0FF)]/5",
published: "border-[var(--color-malachite,#64FFDA)]/30 bg-[var(--color-malachite,#64FFDA)]/5",
}
function ContentCalendar({ items, view = "week", onItemClick, onDateClick, loading = false, className, ...props }: ContentCalendarProps) {
const today = new Date()
const weekDays: Date[] = []
const start = new Date(today)
start.setDate(today.getDate() - today.getDay() + 1)
for (let i = 0; i < 7; i++) {
weekDays.push(new Date(start.getTime() + i * 86400000))
}
return (
<div data-slot="content-calendar" data-portal="https://design.nyuchi.com/components/content-calendar" role="grid" aria-label="Content calendar" className={cn("rounded-[var(--radius-xl,17px)] border border-border bg-card p-4", className)} {...props}>
<div className="grid grid-cols-7 gap-2">
{weekDays.map(day => {
const key = day.toISOString().split("T")[0]
const dayItems = items.filter(item => item.date === key)
const isToday = key === today.toISOString().split("T")[0]
return (
<div key={key} className="min-h-[100px]" onClick={() => onDateClick?.(key)}>
<div className={cn("mb-1 text-center text-[10px] font-medium", isToday ? "text-[var(--color-malachite,#64FFDA)]" : "text-muted-foreground")}>
{day.toLocaleDateString(undefined, { weekday: "short" })}
<div className={cn("text-sm", isToday && "font-bold")}>{day.getDate()}</div>
</div>
<div className="space-y-1">
{dayItems.map(item => (
<button key={item.id} onClick={(e) => { e.stopPropagation(); onItemClick?.(item.id) }}
className={cn("w-full rounded-[var(--radius-sm,7px)] border px-1.5 py-1 text-left text-[9px]", statusStyles[item.status])}>
<div className="truncate font-medium">{item.title}</div>
<div className="text-muted-foreground capitalize">{item.type}</div>
</button>
))}
</div>
</div>
)
})}
</div>
</div>
)
}
export { ContentCalendar }
export type { ContentCalendarProps }
npx shadcn@latest add https://mzizi.dev/api/v1/ui/content-calendarFetch this component's metadata and source code from the registry API.
/api/v1/ui/content-calendar