This component is coming soon. This page documents the planned API and usage. Join the developer preview for early access.
Features
- Drag-to-select - Click and drag to set available hours
- Copy schedule - Duplicate one day’s schedule to others
- Timezone support - Display in user’s local timezone
- Presets - Quick-select common schedules
- Date exceptions - Override availability for specific dates
- Real-time sync - Changes saved automatically
Component Usage (Coming Soon)
Basic Embed
Copy
<div id="availability-picker"></div>
<script src="https://cdn.meetergo.com/components.js"></script>
<script>
Meetergo.AvailabilityPicker({
container: '#availability-picker',
userId: 'user-uuid',
availabilityId: 'availability-uuid',
onSave: (availability) => {
console.log('Saved:', availability);
}
});
</script>
React Component
Copy
import { AvailabilityPicker } from '@meetergo/react';
function AvailabilitySettings() {
return (
<AvailabilityPicker
userId={userId}
availabilityId={availabilityId}
timezone="Europe/Berlin"
format="24h"
minInterval={30}
onChange={(schedule) => {
console.log('Changed:', schedule);
}}
onSave={(availability) => {
toast.success('Availability saved!');
}}
/>
);
}
Configuration Options
Copy
Meetergo.AvailabilityPicker({
// Required
container: '#availability-picker',
userId: 'user-uuid',
// Optional - if not provided, uses user's default availability
availabilityId: 'availability-uuid',
// Display options
timezone: 'Europe/Berlin', // User's timezone
format: '24h', // '24h' or '12h'
weekStartsOn: 'monday', // 'monday' or 'sunday'
minInterval: 30, // Minimum interval in minutes (15, 30, 60)
dayStartHour: 6, // First hour to show
dayEndHour: 22, // Last hour to show
// Features
showPresets: true, // Show preset schedule buttons
showCopyDay: true, // Show "copy to other days" option
showExceptions: true, // Show date exception management
autoSave: true, // Save automatically on change
autoSaveDelay: 1000, // Debounce delay in ms
// Styling
theme: {
primaryColor: '#2563eb',
availableColor: '#22c55e',
unavailableColor: '#f3f4f6',
borderRadius: '8px'
},
// Labels (for i18n)
labels: {
title: 'Set your availability',
save: 'Save',
reset: 'Reset',
copyDay: 'Copy to other days',
presets: {
businessHours: 'Business hours (9-17)',
mornings: 'Mornings only',
afternoons: 'Afternoons only',
clear: 'Clear all'
},
days: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
// Callbacks
onChange: (schedule) => {}, // Called on every change
onSave: (availability) => {}, // Called when saved
onError: (error) => {}
});
Schedule Data Format
The component works with this schedule format:Copy
const schedule = [
{
dayOfWeek: 'monday',
intervals: [
{ from: '09:00', to: '12:00' },
{ from: '13:00', to: '17:00' }
]
},
{
dayOfWeek: 'tuesday',
intervals: [
{ from: '09:00', to: '17:00' }
]
},
// ... other days
{
dayOfWeek: 'saturday',
intervals: [] // Not available
},
{
dayOfWeek: 'sunday',
intervals: []
}
];
Current API Implementation
While the component is in development, use the API:Get Availability
Copy
async function getAvailability(userId, availabilityId) {
const response = await fetch(
`https://api.meetergo.com/availability/${availabilityId}?userId=${userId}`,
{
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'x-meetergo-api-user-id': userId
}
}
);
return response.json();
}
Update Availability
Copy
async function updateAvailability(userId, availabilityId, schedule) {
const response = await fetch(
`https://api.meetergo.com/availability/${availabilityId}`,
{
method: 'PATCH',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-meetergo-api-user-id': userId
},
body: JSON.stringify({ schedule })
}
);
return response.json();
}
// Usage
await updateAvailability(userId, availabilityId, [
{
dayOfWeek: 'monday',
intervals: [{ from: '09:00', to: '17:00' }]
},
{
dayOfWeek: 'tuesday',
intervals: [{ from: '09:00', to: '17:00' }]
}
// ... etc
]);
Add Date Exception
Copy
async function addException(userId, startDate, endDate, isAvailable, name) {
const response = await fetch(
'https://api.meetergo.com/availability-exception/user',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'x-meetergo-api-user-id': userId
},
body: JSON.stringify({
startDate,
endDate,
isAvailable,
name
})
}
);
return response.json();
}
// Block off vacation
await addException(userId, '2024-12-24', '2024-12-26', false, 'Christmas');
// Add extra availability
await addException(userId, '2024-12-28', '2024-12-28', true, 'Saturday coverage');
Building Your Own UI
Example React implementation:Copy
import { useState, useEffect } from 'react';
const DAYS = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
const HOURS = Array.from({ length: 24 }, (_, i) => i);
function AvailabilityPickerCustom({ userId, availabilityId }) {
const [schedule, setSchedule] = useState({});
const [isDragging, setIsDragging] = useState(false);
const [dragValue, setDragValue] = useState(true);
useEffect(() => {
loadAvailability();
}, [userId, availabilityId]);
async function loadAvailability() {
const response = await fetch(`/api/availability/${availabilityId}`);
const data = await response.json();
// Convert to grid format
const grid = {};
DAYS.forEach(day => {
grid[day] = {};
HOURS.forEach(hour => {
grid[day][hour] = false;
});
});
data.schedule.forEach(daySchedule => {
daySchedule.intervals.forEach(interval => {
const startHour = parseInt(interval.from.split(':')[0]);
const endHour = parseInt(interval.to.split(':')[0]);
for (let h = startHour; h < endHour; h++) {
grid[daySchedule.dayOfWeek][h] = true;
}
});
});
setSchedule(grid);
}
function handleMouseDown(day, hour) {
setIsDragging(true);
setDragValue(!schedule[day][hour]);
toggleHour(day, hour);
}
function handleMouseEnter(day, hour) {
if (isDragging) {
setSchedule(prev => ({
...prev,
[day]: { ...prev[day], [hour]: dragValue }
}));
}
}
function handleMouseUp() {
setIsDragging(false);
saveSchedule();
}
function toggleHour(day, hour) {
setSchedule(prev => ({
...prev,
[day]: { ...prev[day], [hour]: !prev[day][hour] }
}));
}
async function saveSchedule() {
// Convert grid back to intervals
const newSchedule = DAYS.map(day => {
const intervals = [];
let start = null;
HOURS.forEach(hour => {
if (schedule[day][hour] && start === null) {
start = hour;
} else if (!schedule[day][hour] && start !== null) {
intervals.push({
from: `${start.toString().padStart(2, '0')}:00`,
to: `${hour.toString().padStart(2, '0')}:00`
});
start = null;
}
});
if (start !== null) {
intervals.push({
from: `${start.toString().padStart(2, '0')}:00`,
to: '24:00'
});
}
return { dayOfWeek: day, intervals };
});
await fetch(`/api/availability/${availabilityId}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ schedule: newSchedule })
});
}
return (
<div
className="availability-grid"
onMouseUp={handleMouseUp}
onMouseLeave={handleMouseUp}
>
<div className="header-row">
<div className="time-column"></div>
{DAYS.map(day => (
<div key={day} className="day-header">
{day.slice(0, 3)}
</div>
))}
</div>
{HOURS.filter(h => h >= 6 && h <= 22).map(hour => (
<div key={hour} className="hour-row">
<div className="time-column">
{hour.toString().padStart(2, '0')}:00
</div>
{DAYS.map(day => (
<div
key={`${day}-${hour}`}
className={`cell ${schedule[day]?.[hour] ? 'available' : ''}`}
onMouseDown={() => handleMouseDown(day, hour)}
onMouseEnter={() => handleMouseEnter(day, hour)}
/>
))}
</div>
))}
</div>
);
}
Styles
Copy
.availability-grid {
display: flex;
flex-direction: column;
user-select: none;
}
.header-row, .hour-row {
display: flex;
}
.time-column {
width: 60px;
font-size: 12px;
color: #666;
}
.day-header {
flex: 1;
text-align: center;
font-weight: 600;
padding: 8px;
}
.cell {
flex: 1;
height: 24px;
border: 1px solid #e5e7eb;
cursor: pointer;
transition: background-color 0.1s;
}
.cell:hover {
background-color: #dbeafe;
}
.cell.available {
background-color: #22c55e;
}
Best Practices
Show timezone - Always display which timezone the schedule is in
Auto-save - Save changes automatically with debouncing
Provide presets - Quick buttons for common schedules
Copy functionality - Let users copy one day to others
Mobile support - Touch-friendly for mobile users