+
+
Invite Students
+
You can invite students via an invite link
+
-
+
+
+
+ Copy link
+
+
+ Copied Successfully
+
+
+
+
+
diff --git a/src/lib/components/Course/components/People/store.js b/src/lib/components/Course/components/People/store.js
index 6beba7f5..b338b663 100644
--- a/src/lib/components/Course/components/People/store.js
+++ b/src/lib/components/Course/components/People/store.js
@@ -5,12 +5,10 @@ export const deleteMemberModal = writable({
});
export const invitationModal = writable({
- open: false,
- students: ''
+ open: false
});
export const resetForm = () =>
invitationModal.update(() => ({
- open: false,
- students: ''
+ open: false
}));
diff --git a/src/lib/components/Course/store.ts b/src/lib/components/Course/store.ts
index 1bad049b..fabf860c 100644
--- a/src/lib/components/Course/store.ts
+++ b/src/lib/components/Course/store.ts
@@ -11,6 +11,7 @@ export const course: Writable
= writable({
description: '',
cost: 0,
currency: '',
+ status: 'ACTIVE',
is_certificate_downloadable: false,
certificate_theme: 'professional',
metadata: {
diff --git a/src/lib/components/Org/SideBar.svelte b/src/lib/components/Org/SideBar.svelte
index c497b403..99dd8797 100644
--- a/src/lib/components/Org/SideBar.svelte
+++ b/src/lib/components/Org/SideBar.svelte
@@ -19,12 +19,12 @@
const menuItems = [
{
path: '',
- label: 'Home'
- },
- {
- path: '/quiz',
- label: 'Quizzes'
+ label: 'Dashboard'
},
+ // {
+ // path: '/quiz',
+ // label: 'Quizzes'
+ // },
{
path: '/courses',
label: 'Courses'
diff --git a/src/lib/components/PrimaryButton/constants.js b/src/lib/components/PrimaryButton/constants.js
index a5ac46f8..4b93c17e 100644
--- a/src/lib/components/PrimaryButton/constants.js
+++ b/src/lib/components/PrimaryButton/constants.js
@@ -7,6 +7,7 @@ export const VARIANTS = {
CONTAINED_SUCCESS: 'CONTAINED_SUCCESS',
OUTLINED: 'OUTLINED',
NONE: 'NONE',
+ LINK: 'LINK',
TEXT: 'TEXT',
TEXT_DANGER: 'TEXT_DANGER'
};
@@ -25,6 +26,7 @@ export const VARIANTS_CLASS = {
[VARIANTS.NONE]:
'border-none hover:border-black-300 hover:bg-gray-200 dark:hover:bg-gray-500 text-black',
[VARIANTS.TEXT]: 'text-black hover:underline',
+ [VARIANTS.LINK]: 'text-primary-500 dark:text-primary-500 hover:underline',
[VARIANTS.TEXT_DANGER]:
'text-red-500 hover:border border-t-0 border-l-0 border-r-0 border-red-300'
};
diff --git a/src/lib/utils/constants/routes.ts b/src/lib/utils/constants/routes.ts
index 087d337d..f742a45d 100644
--- a/src/lib/utils/constants/routes.ts
+++ b/src/lib/utils/constants/routes.ts
@@ -7,7 +7,8 @@ export const ROUTE = {
COURSE: '/course',
LOGIN: '/login',
SIGN_UP: '/signup',
- INVITE_SIGNUP: '/invite',
+ INVITE_TEACHER: '/invite/t',
+ INVITE_STUDENT: '/invite/s',
PROFILE: '/profile',
PEOPLE: '/people',
DISCUSSIONS: '/discussions',
@@ -20,7 +21,7 @@ export const PUBLIC_ROUTES = [
`^${ROUTE.HOME}$`,
ROUTE.LOGIN,
ROUTE.SIGN_UP,
- `^${ROUTE.INVITE_SIGNUP}/.*`,
+ `^${ROUTE.INVITE_TEACHER}/.*`,
ROUTE.FORGOT,
ROUTE.RESET,
`^${ROUTE.PAGES}/.*`,
@@ -31,7 +32,8 @@ export const PUBLIC_ROUTES = [
export const ROUTES_TO_HIDE_NAV = [
ROUTE.LOGIN,
ROUTE.SIGN_UP,
- `^${ROUTE.INVITE_SIGNUP}/.*`,
+ `^${ROUTE.INVITE_TEACHER}/.*`,
+ `^${ROUTE.INVITE_STUDENT}/.*`,
ROUTE.FORGOT,
ROUTE.RESET,
ROUTE.ONBOARDING
diff --git a/src/lib/utils/functions/user.ts b/src/lib/utils/functions/user.ts
new file mode 100644
index 00000000..87b677b3
--- /dev/null
+++ b/src/lib/utils/functions/user.ts
@@ -0,0 +1,8 @@
+import { supabase } from '$lib/utils/functions/supabase';
+import type { Profile } from '$lib/components/Course/components/People/types';
+
+export async function getProfile(email: string): Promise {
+ const { data } = await supabase.from('profile').select('*').eq('email', email).single();
+ console.log('getProfile data', data);
+ return data;
+}
diff --git a/src/lib/utils/types/index.ts b/src/lib/utils/types/index.ts
index 98cdc6ff..a9d1b312 100644
--- a/src/lib/utils/types/index.ts
+++ b/src/lib/utils/types/index.ts
@@ -64,6 +64,7 @@ export interface Group {
updated_at?: string;
organization_id?: string /* foreign key to organization.id */;
organization?: Organization;
+ tutors: Profile[];
}
export interface Role {
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index d41e90c9..9be57c7a 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -81,7 +81,7 @@
console.log('Get user profile', authUser);
if (!authUser) {
- goto('/login');
+ goto('/login?redirect=/' + path);
}
// Check if user has profile
diff --git a/src/routes/api/email/invite/+server.js b/src/routes/api/email/invite/+server.js
index ec7439d6..17947ecb 100644
--- a/src/routes/api/email/invite/+server.js
+++ b/src/routes/api/email/invite/+server.js
@@ -15,7 +15,7 @@ export async function POST({ request }) {
const accessToken = request.headers.get('Authorization');
console.log('/POST api/email/invite', body);
- if (!org || !Object.keys(org) || !email) {
+ if (!org || !Object.keys(org) || !email || !accessToken) {
return json(
{ success: false, message: 'Org data and Teacher name are required' },
{ status: 400 }
@@ -43,7 +43,7 @@ export async function POST({ request }) {
orgId: id,
orgSiteName: siteName
});
- const inviteLink = `${origin}/invite/${encodeURIComponent(btoa(inviteData))}`;
+ const inviteLink = `${origin}/invite/t/${encodeURIComponent(btoa(inviteData))}`;
console.log('inviteData', inviteData);
const options = {
diff --git a/src/routes/invite/s/[hash]/+layout.server.ts b/src/routes/invite/s/[hash]/+layout.server.ts
new file mode 100644
index 00000000..73439ae0
--- /dev/null
+++ b/src/routes/invite/s/[hash]/+layout.server.ts
@@ -0,0 +1,31 @@
+import { redirect } from '@sveltejs/kit';
+import { getSupabase, supabase } from '$lib/utils/functions/supabase';
+import { getCurrentOrg } from '$lib/utils/services/org';
+
+if (!supabase) {
+ getSupabase();
+}
+
+export const load = async ({ params = { hash: '' } }) => {
+ try {
+ const courseHashData = atob(decodeURIComponent(params.hash));
+ console.log('courseHashData', courseHashData);
+
+ const { groupId, name, description, orgSiteName } = JSON.parse(courseHashData);
+
+ if (!groupId || !name || !description || !orgSiteName) {
+ throw 'Validation failed';
+ }
+ const currentOrg = await getCurrentOrg(orgSiteName, true);
+
+ return {
+ groupId,
+ name,
+ description,
+ currentOrg
+ };
+ } catch (error) {
+ console.error('Error decoding course invite params.hash', error);
+ throw redirect(301, '/404');
+ }
+};
diff --git a/src/routes/invite/s/[hash]/+page.svelte b/src/routes/invite/s/[hash]/+page.svelte
new file mode 100644
index 00000000..18f29853
--- /dev/null
+++ b/src/routes/invite/s/[hash]/+page.svelte
@@ -0,0 +1,82 @@
+
+
+
+ Join {data.name} on ClassroomIO
+
+
+
+
+
{data.name}
+
{data.description}
+
+
+
+
diff --git a/src/routes/invite/[hash]/+layout.server.ts b/src/routes/invite/t/[hash]/+layout.server.ts
similarity index 59%
rename from src/routes/invite/[hash]/+layout.server.ts
rename to src/routes/invite/t/[hash]/+layout.server.ts
index 8dcb5fd3..743bb377 100644
--- a/src/routes/invite/[hash]/+layout.server.ts
+++ b/src/routes/invite/t/[hash]/+layout.server.ts
@@ -1,7 +1,14 @@
import { redirect } from '@sveltejs/kit';
import { getCurrentOrg } from '$lib/utils/services/org';
-import { getSupabase } from '$lib/utils/functions/supabase';
+import { getSupabase, supabase } from '$lib/utils/functions/supabase';
+import { getProfile } from '$lib/utils/functions/user';
+if (!supabase) {
+ getSupabase();
+}
+
+// we need to know if the email exists or not.
+// with this we can only ask the user to accept
export const load = async ({ params = { hash: '' } }) => {
try {
const hashData = atob(decodeURIComponent(params.hash));
@@ -9,13 +16,16 @@ export const load = async ({ params = { hash: '' } }) => {
const { orgId, email, orgSiteName } = JSON.parse(hashData);
- getSupabase();
const _currentOrg = await getCurrentOrg(orgSiteName, true);
+ const profile = await getProfile(email);
+ console.log('profile data', profile);
+
return {
orgId,
email,
- currentOrg: _currentOrg
+ currentOrg: _currentOrg,
+ profile
};
} catch (error) {
console.error('Error decoding invite params.hash', error);
diff --git a/src/routes/invite/[hash]/+page.svelte b/src/routes/invite/t/[hash]/+page.svelte
similarity index 58%
rename from src/routes/invite/[hash]/+page.svelte
rename to src/routes/invite/t/[hash]/+page.svelte
index 0ac809b1..06edeb4b 100644
--- a/src/routes/invite/[hash]/+page.svelte
+++ b/src/routes/invite/t/[hash]/+page.svelte
@@ -10,11 +10,11 @@
} from '$lib/utils/functions/validator';
import { SIGNUP_FIELDS } from '$lib/utils/constants/authentication';
import AuthUI from '$lib/components/AuthUI/index.svelte';
- import { currentOrg } from '$lib/utils/store/org';
+ import { currentOrg, currentOrgPath } from '$lib/utils/store/org';
import { setTheme } from '$lib/utils/functions/theme';
import type { CurrentOrg } from '$lib/utils/types/org.js';
import { onMount } from 'svelte';
- import Error from '../../+error.svelte';
+ import type { Profile } from '$lib/components/Course/components/People/types';
export let data;
@@ -34,7 +34,10 @@
let formRef: HTMLFormElement;
async function handleSubmit() {
- const validationRes = authValidation(fields);
+ const validationRes = authValidation({
+ ...fields,
+ email: 'test@gmail.com' // validation for this ema
+ });
console.log('validationRes', validationRes);
if (Object.keys(validationRes).length) {
@@ -44,40 +47,44 @@
try {
loading = true;
- // Signup
- const { data: signupData, error } = await supabase.auth.signUp({
- email: data.email,
- password: fields.password
- });
+ let profile: Profile | null = data.profile;
- console.log('Signup', signupData);
- if (error) throw error;
+ if (!data.profile) {
+ // Signup
+ const { data: signupData, error } = await supabase.auth.signUp({
+ email: data.email,
+ password: fields.password
+ });
- if (!signupData.user) {
- throw 'User cannot be created ';
+ console.log('Signup', signupData);
+ if (error) throw error;
+
+ if (!signupData.user) {
+ throw 'User cannot be created ';
+ }
+
+ // Insert profile
+ const userId = signupData.user.id;
+ const profileRes = await supabase
+ .from('profile')
+ .insert({
+ id: userId,
+ username: fields.name.toLowerCase().replace(' ', '-') + new Date().getTime(),
+ fullname: fields.name,
+ email: data.email
+ })
+ .select();
+
+ console.log('Insert profile', profileRes.data);
+
+ if (profileRes.error) {
+ throw profileRes.error;
+ }
+
+ profile = profileRes.data[0] || {};
}
- // Insert profile
- const userId = signupData.user.id;
- const profileRes = await supabase
- .from('profile')
- .insert({
- id: userId,
- username: fields.name.toLowerCase().replace(' ', '-') + new Date().getTime(),
- fullname: fields.name,
- email: data.email
- })
- .select();
-
- console.log('Insert profile', profileRes.data);
-
- if (profileRes.error) {
- throw profileRes.error;
- }
-
- const profile = profileRes.data[0] || {};
-
- if (!profile.id) {
+ if (!profile?.id) {
throw 'Unable to create profile';
}
@@ -91,12 +98,23 @@
.match({ email: data.email, organization_id: data.currentOrg?.id });
console.log('Update member response', updateMemberRes);
- formRef?.reset();
- return goto('/login');
+ const res = await supabase.auth.signInWithPassword({
+ email: data.email,
+ password: fields.password
+ });
+
+ if (res.error) {
+ throw res.error;
+ }
+
+ formRef?.reset();
+ return goto($currentOrgPath);
} catch (error) {
if (error instanceof Error) {
submitError = error.message;
+ } else {
+ submitError = error?.toString() || '';
}
} finally {
loading = false;
@@ -116,6 +134,7 @@
$: disableSubmit = getDisableSubmit(fields);
$: setCurOrg(data.currentOrg as CurrentOrg);
+ $: console.log('data.profile', data.profile);
@@ -132,7 +151,13 @@
bind:formRef
>
-
Create a free account
+
+ {#if data.profile}
+ Log in to join
+ {:else}
+ Create a free account to join
+ {/if}
+
-
+ {#if !data.profile}
+
+ {/if}
-
+ {#if !data.profile}
+
+ {/if}
{#if submitError}
{submitError}
{/if}
@@ -184,7 +213,7 @@
{#if $profile.id}
diff --git a/src/routes/signup/+page.svelte b/src/routes/signup/+page.svelte
index e561de8e..db2de514 100644
--- a/src/routes/signup/+page.svelte
+++ b/src/routes/signup/+page.svelte
@@ -1,5 +1,6 @@