// DEPLOY_CONFIG: {"triggers": [{"name": "Blocker Posted Alert", "on": "collection.add", "collection": "blockers", "actions": [{"type": "email", "to": "team.lead@company.com", "subject": "New blocker posted", "body": "A new blocker was posted:\n\n{{blocker_text}}"}]}]}
import { useState } from 'react';
import { useAuth, useCollection, useReactions, generatePDF } from '@deplixo/sdk';
import { Header } from './components/Header.jsx';
import { StandupBoard } from './components/StandupBoard.jsx';
import { StandupTimeline } from './components/StandupTimeline.jsx';
function ReactionBar({ targetId }) {
const { counts, toggle, loading } = useReactions(targetId);
const emojis = ['👍', '❤️', '🎉', '🔥', '👀'];
if (loading) return null;
return (
{emojis.map(emoji => (
))}
);
}
function App() {
const { user, loading, login, logout } = useAuth();
const [activeTab, setActiveTab] = useState('board');
if (loading) {
return (
);
}
if (!user) {
return (
📋
Daily Standup Board
Log your progress, share blockers, stay aligned as a team.
);
}
// PROGRESS:sc_001:complete:Setting up authentication and navigation
return (
{activeTab === 'board' && (
Quick reactions
Teammates can react to any standup entry with emoji feedback.
)}
{activeTab === 'timeline' && }
);
}
function WeeklySummaryPDFExport() {
const summaryRef = useState(null)[0];
const { items, loading } = useCollection('standups');
const [exporting, setExporting] = useState(false);
const groupedSummary = items.reduce((acc, item) => {
if (!item) return acc;
const author = item.authorName || item.userName || item.name || 'Team member';
const dateValue = item.createdAt || item.date || item.updatedAt;
const dateKey = dateValue ? new Date(dateValue).toLocaleDateString() : 'Unknown date';
if (!acc[dateKey]) acc[dateKey] = [];
acc[dateKey].push({
author,
yesterday: item.yesterday || item.progress || item.done || '',
today: item.today || item.plans || item.next || '',
blockers: item.blockers || item.blocker || ''
});
return acc;
}, {});
const handleExport = async () => {
if (!summaryRef || exporting) return;
setExporting(true);
try {
await generatePDF(summaryRef, {
filename: 'weekly-standup-summary.pdf',
margin: 10
});
} finally {
setExporting(false);
}
};
const summaryDates = Object.keys(groupedSummary).sort((a, b) => new Date(b) - new Date(a));
return (
Weekly standup summary
Download a PDF of the week’s updates for sharing or archiving.
{loading
? 'Loading weekly summary…'
: `${summaryDates.length} day${summaryDates.length === 1 ? '' : 's'} included in the export.`}
Weekly Standup Summary
Generated on {new Date().toLocaleDateString()}
{summaryDates.length === 0 ? (
No standup entries were found for this week.
) : (
summaryDates.map((date) => (
{date}
{groupedSummary[date].map((entry, index) => (
{entry.author}
Yesterday: {entry.yesterday || '—'}
Today: {entry.today || '—'}
Blockers: {entry.blockers || 'None'}
))}
))
)}
);
}
ReactDOM.createRoot(document.getElementById("root")).render();