Skip to content

feat: Add admin console UI with outreach and onboarding updates#96

Merged
nfebe merged 1 commit into
devfrom
feat/admin-engagement-metrics
Jun 27, 2026
Merged

feat: Add admin console UI with outreach and onboarding updates#96
nfebe merged 1 commit into
devfrom
feat/admin-engagement-metrics

Conversation

@nfebe

@nfebe nfebe commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Adds the admin console UI plus marketing and onboarding refreshes.

Admin (avatar menu, admins only) has its own left-rail shell:

  • Overview — KPI strip, area charts, and Most active users / Most used features rankings.
  • Demographics — users by country, language and currency.
  • Users — a searchable table whose rows open a detailed profile (preferences + per-feature counts).
  • Outreach — a history of sent emails with a + to compose; the composer has a markdown body with a formatting toolbar, a header image, attachments, audience or specific-user targeting, and a live preview of the rendered email.

Marketing / design, aligned to the assistant-first direction:

  • Login slides now lead with the assistant, Plaid integrations, and any-format import, ending on a playful illustrated slide.
  • The onboarding flow is modernized (brand-washed background, illustrated step tiles, a country step).
  • The shared empty state gets a Solar illustration that cascades app-wide; the learning modal is refreshed; emoji and decorative left-stripe cards are replaced with vector icons.

Fixes: the country list (a .split precedence bug) and a configs-out-of-scope crash on login.

Tests: 405 passing; build green.

Add an admin area, reached from the avatar menu when the signed-in user
is an administrator. It has its own left-rail shell with an overview
dashboard (KPIs, charts and rankings), demographics, a searchable user
table whose rows open a detailed profile, and outreach: a history of
sent emails plus a composer with a formatted (markdown) body, a header
image, attachments, audience or specific-user targeting, and a live
preview of the rendered email.

Refresh the marketing surfaces to match the assistant-first direction:
the login slides now lead with the assistant and bank integrations, the
onboarding flow gets a brand-washed background and illustrated steps with
a country step, and the emoji and stripe cards in onboarding and the
learning modal are replaced with vector icons and clean surfaces.
@sourceant

sourceant Bot commented Jun 27, 2026

Copy link
Copy Markdown

Code Review Summary

This PR introduces a comprehensive Admin Console and refreshes the onboarding/marketing UI. It includes new metrics dashboards, user management, and an outreach campaign tool with markdown support. It also fixes several login-related crashes.

🚀 Key Improvements

  • New Admin Console at /admin with KPI metrics and ApexCharts integration.
  • Refined onboarding flow with iconography and better layout.
  • Modernized marketing assets and login carousel slides.
  • Fixed a crash in pages/login.vue where configs was out of scope.

💡 Minor Suggestions

  • Standardize the URL normalization in the outreach composer.
  • Avoid hardcoding 'en' locale for country name resolution.

@sourceant sourceant Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review complete. See the overview comment for a summary.

}
};

const normalizeUrl = (url: string): string => (/^https?:\/\//i.test(url) ? url : `https://${url}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex ^https?:\/\/ only validates the protocol but not the rest of the URL structure. A user could enter https:// and it would pass.

Suggested change
const normalizeUrl = (url: string): string => (/^https?:\/\//i.test(url) ? url : `https://${url}`);
const normalizeUrl = (url: string): string => {
if (!url) return '';
const trimmed = url.trim();
return /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
};

<div class="preview__frame">
<iframe
v-if="previewHtml"
:srcdoc="previewHtml"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using srcdoc in an iframe, it is safer to use the sandbox attribute without allow-scripts unless strictly necessary to prevent XSS from the rendered markdown.

Suggested change
:srcdoc="previewHtml"
:srcdoc="previewHtml"
class="preview__iframe"
sandbox="allow-same-origin"

Comment thread middleware/admin.ts
@@ -0,0 +1,15 @@
export default defineNuxtRouteMiddleware(async () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The middleware relies on isAuthenticated which is usually a client-side reactive state. In a SSR context (Nuxt), ensure useAuth handles the initialization properly or wrap this in a client-side check if the API isn't ready.

Suggested change
export default defineNuxtRouteMiddleware(async () => {
export default defineNuxtRouteMiddleware(async () => {
const { user, isAuthenticated, fetchUser } = useAuth();
if (process.server) return;
if (!isAuthenticated.value) {
return navigateTo('/login');
}
if (user.value && typeof user.value.is_admin === 'undefined') {
await fetchUser();
}
if (!user.value?.is_admin) {
return navigateTo('/dashboard');
}
});

Comment thread utils/countries.ts
if (cache) return cache;
let display: Intl.DisplayNames | null = null;
try {
display = new Intl.DisplayNames(['en'], { type: 'region' });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The locale is hardcoded to 'en'. For a localized app, it should use the user's current language preference.

Suggested change
display = new Intl.DisplayNames(['en'], { type: 'region' });
const { locale } = useI18n ? useI18n() : { locale: { value: 'en' } };
display = new Intl.DisplayNames([locale.value], { type: 'region' });

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying trakli-dev with  Cloudflare Pages  Cloudflare Pages

Latest commit: a6820c7
Status: ✅  Deploy successful!
Preview URL: https://03d5473f.trakli-dev.pages.dev
Branch Preview URL: https://feat-admin-engagement-metric.trakli-dev.pages.dev

View logs

@nfebe nfebe merged commit 5b69a84 into dev Jun 27, 2026
6 checks passed
@nfebe nfebe deleted the feat/admin-engagement-metrics branch June 27, 2026 20:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant