Added scheduled end of shift message & cleaned up tv mode layout
This commit is contained in:
2
convex/_generated/api.d.ts
vendored
2
convex/_generated/api.d.ts
vendored
@@ -15,6 +15,7 @@ import type {
|
||||
} from "convex/server";
|
||||
import type * as CustomPassword from "../CustomPassword.js";
|
||||
import type * as auth from "../auth.js";
|
||||
import type * as crons from "../crons.js";
|
||||
import type * as files from "../files.js";
|
||||
import type * as http from "../http.js";
|
||||
import type * as statuses from "../statuses.js";
|
||||
@@ -30,6 +31,7 @@ import type * as statuses from "../statuses.js";
|
||||
declare const fullApi: ApiFromModules<{
|
||||
CustomPassword: typeof CustomPassword;
|
||||
auth: typeof auth;
|
||||
crons: typeof crons;
|
||||
files: typeof files;
|
||||
http: typeof http;
|
||||
statuses: typeof statuses;
|
||||
|
@@ -36,6 +36,22 @@ export const getUser = query(async (ctx) => {
|
||||
};
|
||||
});
|
||||
|
||||
export const getAllUsers = query(async (ctx) => {
|
||||
const users = await ctx.db.query('users').collect();
|
||||
return users.map((u) => ({
|
||||
id: u._id,
|
||||
email: u.email ?? null,
|
||||
name: u.name ?? null,
|
||||
image: u.image ?? null,
|
||||
}));
|
||||
});
|
||||
|
||||
export const getAllUserIds = query(async (ctx) => {
|
||||
const users = await ctx.db.query('users').collect();
|
||||
const userIds = users.map((u) => u._id);
|
||||
return userIds;
|
||||
});
|
||||
|
||||
export const updateUserName = mutation({
|
||||
args: {
|
||||
name: v.string(),
|
||||
|
15
convex/crons.ts
Normal file
15
convex/crons.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
// convex/crons.ts
|
||||
import { cronJobs } from 'convex/server';
|
||||
import { api } from './_generated/api';
|
||||
|
||||
const crons = cronJobs();
|
||||
|
||||
// Runs at 5:00 PM America/Chicago, Monday–Friday.
|
||||
// Convex will handle DST if your project version supports `timeZone`.
|
||||
crons.cron(
|
||||
'End of shift (weekdays 5pm CT)',
|
||||
'0 22 * * 1-5',
|
||||
api.statuses.endOfShiftUpdate,
|
||||
);
|
||||
|
||||
export default crons;
|
@@ -23,7 +23,7 @@ export default defineSchema({
|
||||
userId: v.id('users'),
|
||||
message: v.string(),
|
||||
updatedAt: v.number(),
|
||||
updatedBy: v.id('users'),
|
||||
updatedBy: v.optional(v.id('users')),
|
||||
})
|
||||
.index('by_user', ['userId'])
|
||||
.index('by_user_updatedAt', ['userId', 'updatedAt']),
|
||||
|
@@ -3,9 +3,12 @@ import { getAuthUserId } from '@convex-dev/auth/server';
|
||||
import {
|
||||
type MutationCtx,
|
||||
type QueryCtx,
|
||||
action,
|
||||
internalMutation,
|
||||
mutation,
|
||||
query,
|
||||
} from './_generated/server';
|
||||
import { api } from './_generated/api';
|
||||
import type { Doc, Id } from './_generated/dataModel';
|
||||
import { paginationOptsValidator } from 'convex/server';
|
||||
|
||||
@@ -135,6 +138,29 @@ export const bulkCreate = mutation({
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Update all statuses for all users.
|
||||
*/
|
||||
export const updateAllStatuses = mutation({
|
||||
args: { message: v.string() },
|
||||
handler: async (ctx, args) => {
|
||||
const userIds = await ctx.runQuery(api.auth.getAllUserIds);
|
||||
const updatedAt = Date.now();
|
||||
const statusIds: Id<'statuses'>[] = [];
|
||||
for (const userId of userIds) {
|
||||
await ensureUser(ctx, userId);
|
||||
const statusId = await ctx.db.insert('statuses', {
|
||||
message: args.message,
|
||||
userId,
|
||||
updatedAt,
|
||||
});
|
||||
await ctx.db.patch(userId, { currentStatusId: statusId });
|
||||
statusIds.push(statusId);
|
||||
}
|
||||
return { statusIds };
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Current status for a specific user.
|
||||
* - Uses users.currentStatusId if present,
|
||||
@@ -199,7 +225,7 @@ export const getCurrentForAll = query({
|
||||
|
||||
// Updated by (if different) + URL
|
||||
let updatedByUser: StatusRow['user'] | null = null;
|
||||
if (curStatus && curStatus.updatedBy !== u._id) {
|
||||
if (curStatus && curStatus.updatedBy && curStatus.updatedBy !== u._id) {
|
||||
const updater = await ctx.db.get(curStatus.updatedBy);
|
||||
if (!updater) throw new ConvexError('Updater not found.');
|
||||
const updaterImageId = getImageId(updater);
|
||||
@@ -286,7 +312,9 @@ export const listHistory = query({
|
||||
for (const s of result.page) {
|
||||
const owner = await getDisplay(s.userId);
|
||||
const updatedBy =
|
||||
s.updatedBy !== s.userId ? await getDisplay(s.updatedBy) : null;
|
||||
(s.updatedBy && s.updatedBy !== s.userId)
|
||||
? await getDisplay(s.updatedBy)
|
||||
: null;
|
||||
|
||||
statuses.push({
|
||||
user: owner,
|
||||
@@ -309,3 +337,25 @@ export const listHistory = query({
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const endOfShiftUpdate = action({
|
||||
handler: async (ctx) => {
|
||||
const now = new Date(
|
||||
new Date().toLocaleString('en-US', {
|
||||
timeZone: 'America/Chicago',
|
||||
}),
|
||||
);
|
||||
const day = now.getDay();
|
||||
const hour = now.getHours();
|
||||
const minute = now.getMinutes();
|
||||
if (day == 0 || day === 6) return;
|
||||
if (hour === 12) {
|
||||
await ctx.runMutation(api.statuses.updateAllStatuses, {
|
||||
message: 'End of shift',
|
||||
});
|
||||
} else if (hour === 11) {
|
||||
const ms = ((60-minute) % 60) * 60 * 1000;
|
||||
await ctx.scheduler.runAfter(ms, api.statuses.endOfShiftUpdate);
|
||||
} else return;
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user