Introduces a new "Executive Meetings Management" module with database schema, API endpoints, and UI components, designed to run independently without altering existing functionalities.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: e463ac71-2b1f-4b47-8b94-ca9526e6f427
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/3E2mNig
Replit-Helium-Checkpoint-Created: true
## Socket.IO broadcasts (core task):
- POST /users/:id/roles: uses .returning() to emit apps_changed only when row inserted
- DELETE /users/:id/roles/:roleName: uses .returning() to emit only when row deleted
- Added emitAppsChangedToRoleHolders(roleId) helper to realtime.ts
- New role-permission endpoints in roles.ts, emit only on effective changes:
- GET /roles/:id/permissions — list permissions for a role
- POST /roles/:id/permissions — assign; emits to role holders on actual insert
- DELETE /roles/:id/permissions/:permId — remove; emits only if row was deleted
## Bug fix: admin panel not showing disabled apps
- Added GET /api/admin/apps (requireAdmin) returning ALL apps from DB
- Updated admin.tsx: useQuery → /api/admin/apps with ADMIN_APPS_KEY constant
- All admin.tsx mutation handlers invalidate ADMIN_APPS_KEY
## UI fix: disabled app cards nearly invisible (opacity-60 on glass)
- Gray background + grayscale icon + muted text + stronger Disabled badge
Replit-Task-Id: f439ec75-bcd5-4030-8ee1-83a5d976f1a1
## DB: removed 11 duplicate rows from app_permissions table
## Task #80 — Tell receivers when an order is no longer available to claim
### Problem
When a receiver tried to act on an order that had already been cancelled, completed,
or claimed by someone else, the UI showed a generic "Could not complete the action"
toast. The stale card also stayed in the list, requiring a manual refresh.
### Changes
**artifacts/api-server/src/routes/service-orders.ts**
- PATCH /orders/:id/confirm-receipt: after a failed atomic claim, query the current
order status; return 409 `order_unavailable` if it's cancelled/completed (vs the
existing 409 `already_claimed` for when it was grabbed by someone else first)
- PATCH /orders/:id/status (preparing/completed branch): terminal-state check runs
BEFORE permission gating — returns 409 `order_unavailable` when order is already
cancelled/completed instead of ever hitting 403 Forbidden
- PATCH /orders/:id/status (cancel branch): same — terminal-state check moved to
the top of the branch so non-admin receivers trying to cancel an already-terminal
order get 409 `order_unavailable` (not 403 Forbidden which would never let the UI
remove the stale card)
**artifacts/tx-os/src/pages/orders-incoming.tsx**
- handleConfirmReceipt onError: distinguish 409 `order_unavailable` from
`already_claimed`, show specific toast, remove stale card via invalidate()
- handleSetStatus onError: same pattern — specific toast + invalidate() on
`order_unavailable`
- handleCancel onError: same pattern
**artifacts/tx-os/src/locales/en.json + ar.json**
- Added `incomingOrders.orderUnavailable` ("This order is no longer available" /
"هذا الطلب لم يعد متاحاً")
## Bonus fix — Disabled app disappears from admin panel (user-reported)
### Problem
When an admin disabled an app via the toggle, the app disappeared from the admin
panel too (isActive filter applied to everyone), making it impossible to re-enable
without direct DB access.
### Changes
**artifacts/api-server/src/routes/apps.ts**
- getVisibleAppsForUser: admins now receive ALL apps including inactive ones via
conditional $dynamic() Drizzle query; non-admins still only see active apps
**artifacts/tx-os/src/pages/home.tsx**
- Filter orderedApps to only active apps before rendering so inactive apps don't
appear on the home screen even for admins
**artifacts/tx-os/src/pages/admin.tsx**
- Inactive app cards show reduced opacity + a "Disabled/معطّل" badge
**artifacts/tx-os/src/locales/en.json + ar.json**
- Added `admin.appDisabled` ("Disabled" / "معطّل")
Replit-Task-Id: 8d6fade8-e76c-4d3c-864b-59007688c12c
Introduced a new hook `useTopbarClockVisibility` in `artifacts/teaboy-os/src/components/clock.tsx` to manage the visibility of the top bar clock, separate from the home clock widget. Updated `artifacts/teaboy-os/src/pages/home.tsx` to utilize this new hook, allowing the eye icon to toggle the top bar clock's visibility.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 08cff793-79ae-45ad-9958-d029baf1737d
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/PwtbShH
Replit-Helium-Checkpoint-Created: true
Per user request, the home page no longer shows the time-of-day greeting
("مساء الخير، {name}") nor the day-name + Gregorian date subtitle. The
apps grid (and the admin stats row when applicable) now sits directly
under the top bar.
Changes (artifacts/teaboy-os/src/pages/home.tsx):
- Removed the entire greeting block (the wrapper div, the <h1> greeting
and the date <p>) from the Main Content section.
- Removed the now-unused `dayName`, `gregorianDate` and `greeting`
locals plus the `formatWeekday` and `greetingKey` imports.
- Kept `displayName` (still used in the avatar header) and the
`home.greeting.*` translation keys (left in place; cheap to keep and
avoids touching unrelated locale files).
Mid-task fix:
- First pass also dropped `displayName` which broke the avatar
(`displayName is not defined`). Restored it; `displayName` is needed
by the user-card initials and name labels.
Validation:
- `pnpm --filter @workspace/api-server test` — 18/18 pass
- `pnpm --filter @workspace/teaboy-os test:e2e` — 3/3 pass
Notes:
- Pre-existing TypeScript errors in admin.tsx / clock-style-picker.tsx /
clock.tsx are unrelated to this task (codegen drift from earlier
tasks).
Original task #58 was to add a dismissible hint when the home clock is
hidden. The hint was implemented and verified end-to-end (EN + AR/RTL),
but the user then asked to remove it. This commit removes the hint and
also removes the "تطبيقاتي · N" / "My Apps · N" header above the apps
grid per the user's request to show the apps directly.
Changes:
- artifacts/teaboy-os/src/pages/home.tsx
- Removed the hidden-clock hint UI block, its session-storage state
(clockHintDismissed) and the related useEffect/dismiss helper.
- Removed the unused Clock-icon lucide import.
- Removed the "My Apps" heading row (h3 + count) above the apps grid.
- artifacts/teaboy-os/src/locales/en.json, ar.json
- Removed the new keys: home.clockStyle.hiddenHint,
hiddenHintAction, dismissHint.
Rebase notes:
- Rebased onto main (a05249f). Two conflicts:
* artifacts/teaboy-os/public/opengraph.jpg — binary asset unrelated
to this task; took main's version (--ours during rebase).
* artifacts/teaboy-os/src/pages/home.tsx — main re-styled the apps
grid header (flex/gap layout with inline " · N" count) and added
a useGridCols() hook. My commit removes that header entirely per
user request, so kept the user-requested removal while preserving
main's useGridCols() addition. No semantic divergence — just the
deletion still applies cleanly to the new header markup.
Notes:
- Clock can still be hidden via the X on the clock tile and shown
again via the clock-style popover in the top bar (existing behavior).
- Translation key home.myApps is still defined but no longer used on
the home page; left in place to avoid touching other consumers.
- Pre-existing TypeScript errors on AuthUser.clockStyle/clockHour12
in chat.tsx/home.tsx are unrelated to this task.
Replit-Task-Id: 14544719-933c-49f8-84a0-6577d06fbc14
Task #41: Show a usage history popup when admins click a top
apps row or a most-active users row on the admin dashboard.
Changes:
- API: extracted the existing range/from/to parser in
artifacts/api-server/src/routes/stats.ts into a shared
parseRangeWindow() helper so the same window logic powers
the existing /stats/admin endpoint and two new ones.
- API: added GET /stats/admin/app-opens/by-app/:appId returning
the last 100 opens for an app inside the selected window,
including the user (id, username, displayName, avatarUrl)
and a totalCount. requireAuth + requireAdmin guarded.
- API: added GET /stats/admin/app-opens/by-user/:userId with
the same shape but per-app metadata for each open.
- Spec: added matching paths and AdminAppOpensByApp /
AdminAppOpensByUser schemas in lib/api-spec/openapi.yaml,
reran orval codegen for api-client-react and api-zod.
- UI: in artifacts/teaboy-os/src/pages/admin.tsx the Top apps
and Most active users leaderboard rows now open a drill-in
modal instead of immediately navigating away. The modal
shows a scrollable timeline of recent opens (timestamp +
user/app), respects the dashboard's current range selector
(7d/30d/90d/custom), and exposes an "Edit app" / "View user"
footer button that preserves the previous jump-to behaviour.
Loading, error, and empty states are handled.
- i18n: added admin.dashboard.drillIn keys in en.json and
ar.json (titles, subtitle, empty/error, footer buttons).
Verification: pnpm run typecheck passes.
Follow-ups proposed: #47 (clickable rows inside the popup),
Replit-Task-Id: f2fbe652-a788-4f25-9fb2-9ef2c535c8da
#48 (paginate beyond 100 opens).
Adds a new `AnalogClockWidget` component with Roman numerals and a sweeping second hand, integrated into the home page. The widget's visibility can now be toggled via the `ClockStylePicker` and is persisted in `localStorage`.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 0a1df300-b156-461b-90d5-e9874f25113f
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/YPEna1J
Replit-Helium-Checkpoint-Created: true
Adds three new tables (notes, note_items, note_shares) for storing note data, checklist items, and sharing permissions. Includes API endpoints and UI considerations for creating, editing, viewing, and managing notes, with features like pinning, color-coding, archiving, and user sharing.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: f9708c33-0313-4d52-9aaf-39f564d4af34
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/pCDTgLS
Replit-Helium-Checkpoint-Created: true
Update the services page layout to display smaller service cards with a square aspect ratio and increased column count, along with adjustments to padding, image sizes, and text truncation for a more compact design.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: b2994de5-2015-4dec-9ec2-f273f1b2b8e7
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/pCDTgLS
Replit-Helium-Checkpoint-Created: true
Add editable footer text fields to site settings, update OpenAPI schema and API client, refactor the login page to display AI-generated artwork and use dynamic footer text, and remove the old logo and welcome heading.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: a650b496-7c3c-427e-bfbe-77bc8b9b5dd2
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/gdgNDb6
Replit-Helium-Checkpoint-Created: true
- New user_app_orders composite-PK table (user_id, app_id) -> sort_order
- Added GET helper getVisibleAppsForUser that LEFT JOINs user order
and sorts by COALESCE(user_sort, app.sort_order, name)
- New PUT /api/me/app-order endpoint validates payload, filters to
visible apps, dedupes, replaces row set in a transaction
- Frontend: wrapped home apps grid in @dnd-kit DndContext + SortableContext
with PointerSensor (distance:8) and TouchSensor (delay:250 / tolerance:5)
so taps still navigate while a press-and-drag reorders
- Optimistic local state with rollback on error; useEffect skips sync
while a save mutation is in flight to avoid stomping on user changes
- Bottom dock intentionally NOT sortable (per user choice)
- DB schema pushed manually via SQL (drizzle-kit push prompted for
rename ambiguity); regenerated api-zod / api-client-react
- Verified end-to-end: PUT /api/me/app-order returns reordered list
and subsequent GET /api/apps reflects the new per-user order
Implements drag-and-drop functionality for reordering apps using @dnd-kit, adds a new `userAppOrdersTable` to the database schema to store user-specific app order preferences, and introduces a new API endpoint `/api/me/app-order` for updating these preferences.
Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 77cfe984-2c65-4152-bb7a-0df28274fe66
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: e782e35b-00f5-4b9b-8931-63051a25df80
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/c3c252e4-c83d-40ca-9fff-99a3ea60701e/77cfe984-2c65-4152-bb7a-0df28274fe66/PrQkd7G
Replit-Helium-Checkpoint-Created: true