feat: mock exercise template api (#613)

* feat: move mock exercise template to api

* feat: add template migration file

* chore:
- remove exercise templates form api
- rework api to pull exercise templates from db
- add exercise template seed to seed file
- declutter seed file

* chore:
- refactor template fetch to be dependent on the selected tag
- add tag to schema, remote db and template's seed file
- clear remote db's template table and replace data and their respective tags

* chore: add number of questions and center loading screen on the frontend

* chore: pr fixes

* chore: type fixes

* chore:
- move seed functionality to /seed folder
- add typing for individual seed functions
- pr fixes

* chore: pr fixes v2

* update output css

* refactor: update seeding script and schema definitions

- Renamed `seedTypes` to `seedQuestionTypes` for clarity in the seeding process.
- Enhanced the seeding script to include a command-line interface for better usability, allowing specific seed functions to be executed based on flags.
- Removed redundant unique constraints in the schema definitions for `courseNewsfeedComment` and `exerciseTemplate` to streamline database structure.

* feat: add email verification error handling page and update session management

- Introduced a new page for handling email verification errors, providing user-friendly messages based on error types.
- Updated session management logic to improve handling of public routes and session states.
- Enhanced security policies in the Svelte configuration to include additional sources for styles and scripts.
- Removed the old email verification error page to streamline the codebase.

* move the exercise template to cloudflare cdn

---------

Co-authored-by: Rotimi Best <best@classroomio.com>
This commit is contained in:
Adeyemi Adetunji
2025-12-25 05:09:27 +01:00
committed by GitHub
co-authored by Rotimi Best
parent ac3f35a97f
commit 50d6ee3111
263 changed files with 1568 additions and 37195 deletions
@@ -0,0 +1,96 @@
<script lang="ts">
import { page } from '$app/stores';
import { goto } from '$app/navigation';
import { t } from '$lib/utils/functions/translations';
import { Button } from '@cio/ui/base/button';
import { Empty } from '@cio/ui/custom/empty';
import OctagonAlertIcon from '@lucide/svelte/icons/octagon-alert';
import TriangleAlertIcon from '@lucide/svelte/icons/triangle-alert';
let type = $derived($page.url.searchParams.get('error') || 'unknown');
let { message, title } = $derived.by(() => {
const fields = {
title: '',
message: '',
};
if (!type) return fields;
switch (type) {
case 'token_expired':
fields.title = $t('email_verification.errors.token_expired.title');
fields.message = $t('email_verification.errors.token_expired.message');
break;
case 'email_mismatch':
fields.title = $t('email_verification.errors.email_mismatch.title');
fields.message = $t('email_verification.errors.email_mismatch.message');
break;
case 'legacy_method_blocked':
fields.title = $t('email_verification.errors.legacy_blocked.title');
fields.message = $t('email_verification.errors.legacy_blocked.message');
break;
case 'database_error':
fields.title = $t('email_verification.errors.database.title');
fields.message = $t('email_verification.errors.database.message');
break;
default:
fields.title = $t('email_verification.errors.unknown.title');
fields.message = $t('email_verification.errors.unknown.message');
}
return fields;
});
function handleSupport() {
window.open(
'mailto:help@classroomio.com?subject=Email Verification Issue&body=Error Type: ' + type,
'_blank'
);
}
</script>
<svelte:head>
<title>Email Verification Error - ClassroomIO</title>
<meta name="description" content="There was an issue verifying your email address." />
</svelte:head>
<Empty
title={title}
description={message}
icon={OctagonAlertIcon}
variant="page"
layout="full-page"
showLogo={true}
class="h-fit! flex-none! max-h-none!"
>
{#if type === 'legacy_method_blocked'}
<div
class="rounded-md border border-yellow-200 bg-yellow-50 p-4 dark:border-yellow-800 dark:bg-yellow-900/20"
>
<div class="flex items-center">
<TriangleAlertIcon class="h-5 w-5 flex-shrink-0 text-yellow-400" />
<div class="ml-3">
<h3 class="text-sm font-medium text-yellow-800 dark:text-yellow-200">
{$t('email_verification.security_notice.title')}
</h3>
<p class="mt-1 text-xs text-yellow-700 dark:text-yellow-300">
{$t('email_verification.security_notice.message')}
</p>
</div>
</div>
</div>
{/if}
<div class="lex w-full flex-col justify-center gap-4 md:flex-row">
<Button
onclick={handleSupport}
variant="ghost"
>
{$t('email_verification.actions.contact_support')}
</Button>
<Button
onclick={() => goto('/')}
>
{$t('email_verification.actions.back_to_dashboard')}
</Button>
</div>
</Empty>