CLASSROOMIO-T-31: Add audience page
Co-authored-by: Rotimi Best <rotimiibitoyeemma@gmail.com> Merge-request: CLASSROOMIO-MR-6 Merged-by: Digdippa Team <digdippa@gmail.com>
This commit is contained in:
committed by
Space Cloud
co-authored by
Rotimi Best
parent
ae8f9ca222
commit
01a1f0f907
@@ -0,0 +1,47 @@
|
||||
<script>
|
||||
import {
|
||||
DataTable,
|
||||
Toolbar,
|
||||
ToolbarContent,
|
||||
ToolbarSearch,
|
||||
Pagination,
|
||||
DataTableSkeleton,
|
||||
} from 'carbon-components-svelte';
|
||||
import { orgAudience } from '../../utils/store/org';
|
||||
|
||||
export let isLoading = false;
|
||||
|
||||
const headers = [
|
||||
{ key: 'name', value: 'Name' },
|
||||
{ key: 'email', value: 'Email' },
|
||||
{ key: 'date_joined', value: 'Date Joined' },
|
||||
];
|
||||
let pageSize = 5;
|
||||
let page = 1;
|
||||
let filteredRowIds = [];
|
||||
let searchValue = '';
|
||||
</script>
|
||||
|
||||
{#if isLoading}
|
||||
<DataTableSkeleton {headers} rows={pageSize} />
|
||||
{:else}
|
||||
<DataTable size="tall" {headers} rows={$orgAudience} {pageSize} {page}>
|
||||
<Toolbar>
|
||||
<ToolbarContent>
|
||||
<ToolbarSearch
|
||||
persistent
|
||||
value={searchValue}
|
||||
shouldFilterRows
|
||||
bind:filteredRowIds
|
||||
/>
|
||||
</ToolbarContent>
|
||||
</Toolbar>
|
||||
</DataTable>
|
||||
{/if}
|
||||
|
||||
<Pagination
|
||||
bind:pageSize
|
||||
bind:page
|
||||
totalItems={filteredRowIds.length}
|
||||
pageSizeInputDisabled
|
||||
/>
|
||||
@@ -0,0 +1,31 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import Box from '../Box/index.svelte';
|
||||
import AudienceList from './AudienceList.svelte';
|
||||
import AudienceEmptyIcon from '../Icons/AudienceEmptyIcon.svelte';
|
||||
import { getOrgAudience } from '../../utils/services/org';
|
||||
import { orgAudience, currentOrg } from '../../utils/store/org';
|
||||
|
||||
let isLoading = false;
|
||||
onMount(async () => {
|
||||
isLoading = true;
|
||||
await getOrgAudience($currentOrg.id);
|
||||
isLoading = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="flex items-center justify-center lg:justify-start flex-wrap my-4 m-auto"
|
||||
>
|
||||
{#if $orgAudience.length || isLoading}
|
||||
<AudienceList {isLoading} />
|
||||
{:else}
|
||||
<Box>
|
||||
<AudienceEmptyIcon />
|
||||
<h3 class="text-2xl my-5">No audience to manage!</h3>
|
||||
<p class="w-1/3 text-center">
|
||||
Manage all your students here and stay connected with them.
|
||||
</p>
|
||||
</Box>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -9,6 +9,7 @@
|
||||
import { addGroupMember } from '../../../../utils/services/courses';
|
||||
import { supabase } from '../../../../utils/functions/supabase';
|
||||
import { profile } from '../../../../utils/store/user';
|
||||
import { currentOrg } from '../../../../utils/store/org';
|
||||
|
||||
let errors = {
|
||||
emails: '',
|
||||
@@ -25,7 +26,7 @@
|
||||
// 1. Create group
|
||||
const { data: newGroup } = await supabase
|
||||
.from('group')
|
||||
.insert({ name: title, description });
|
||||
.insert({ name: title, description, organization_id: $currentOrg.id });
|
||||
|
||||
console.log(`newGroup`, newGroup);
|
||||
const { id: group_id } = newGroup[0];
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<svg
|
||||
width="121"
|
||||
height="120"
|
||||
viewBox="0 0 121 120"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<circle
|
||||
cx="79.7922"
|
||||
cy="32.4026"
|
||||
r="12.5649"
|
||||
stroke="#0F62FE"
|
||||
stroke-width="1.67532"
|
||||
/>
|
||||
<path
|
||||
d="M69.7402 40.7794L74.2444 37.7766C77.6914 35.4786 82.0846 35.1362 85.8461 36.8722L90.6818 39.1041"
|
||||
stroke="#0F62FE"
|
||||
stroke-width="1.67532"
|
||||
/>
|
||||
<circle
|
||||
cx="79.4199"
|
||||
cy="28.68"
|
||||
r="3.81602"
|
||||
stroke="#0F62FE"
|
||||
stroke-width="1.67532"
|
||||
/>
|
||||
<circle
|
||||
cx="106.597"
|
||||
cy="62.5588"
|
||||
r="12.5649"
|
||||
stroke="#0F62FE"
|
||||
stroke-width="1.67532"
|
||||
/>
|
||||
<path
|
||||
d="M96.5455 70.9357L101.05 67.9329C104.497 65.6349 108.89 65.2924 112.651 67.0285L117.487 69.2603"
|
||||
stroke="#0F62FE"
|
||||
stroke-width="1.67532"
|
||||
/>
|
||||
<circle
|
||||
cx="106.225"
|
||||
cy="58.8363"
|
||||
r="3.81602"
|
||||
stroke="#0F62FE"
|
||||
stroke-width="1.67532"
|
||||
/>
|
||||
<circle
|
||||
cx="71.4156"
|
||||
cy="79.3128"
|
||||
r="12.5649"
|
||||
stroke="#0F62FE"
|
||||
stroke-width="1.67532"
|
||||
/>
|
||||
<path
|
||||
d="M61.3636 87.6896L65.8678 84.6868C69.3148 82.3888 73.708 82.0463 77.4695 83.7824L82.3052 86.0143"
|
||||
stroke="#0F62FE"
|
||||
stroke-width="1.67532"
|
||||
/>
|
||||
<circle
|
||||
cx="71.0433"
|
||||
cy="75.5902"
|
||||
r="3.81602"
|
||||
stroke="#0F62FE"
|
||||
stroke-width="1.67532"
|
||||
/>
|
||||
<rect x="5.5" y="49.5" width="24.5" height="5" rx="2.5" stroke="#1339A6" />
|
||||
<rect x="5.5" y="61.5" width="44" height="5" rx="2.5" stroke="#1339A6" />
|
||||
<rect x="5.5" y="73.5" width="44" height="5" rx="2.5" stroke="#1339A6" />
|
||||
<rect x="5.5" y="85.5" width="44" height="5" rx="2.5" stroke="#1339A6" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -248,4 +248,8 @@
|
||||
:global(.app-background-color) {
|
||||
background-color: var(--app-background-color);
|
||||
}
|
||||
|
||||
:global(.bx--data-table-container) {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1 +1,31 @@
|
||||
Audience Page
|
||||
<script>
|
||||
import PrimaryButton from '../../../components/PrimaryButton/index.svelte';
|
||||
import Audience from '../../../components/Audience/index.svelte';
|
||||
|
||||
let isLoading = false;
|
||||
function exportAudience() {
|
||||
isLoading = true;
|
||||
alert('This feature is coming soon');
|
||||
isLoading = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Audience - ClassroomIO</title>
|
||||
</svelte:head>
|
||||
|
||||
<section class="w-full max-w-6xl mx-auto">
|
||||
<div class="py-10 px-5">
|
||||
<div class="flex items-center justify-between mb-10">
|
||||
<h1 class="text-3xl font-bold">Audience</h1>
|
||||
<PrimaryButton
|
||||
label="Export"
|
||||
onClick={exportAudience}
|
||||
isDisabled={isLoading}
|
||||
{isLoading}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Audience />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<title>Courses - ClassroomIO</title>
|
||||
</svelte:head>
|
||||
|
||||
<section class="w-full">
|
||||
<section class="w-full max-w-7xl mx-auto">
|
||||
<div class="py-10 px-5">
|
||||
<div class="flex items-center justify-between mb-10">
|
||||
<h1 class="text-3xl font-bold">Courses</h1>
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
<title>Dashboard - ClassroomIO</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="py-10 px-5">
|
||||
<div class="py-10 px-5 w-full max-w-7xl mx-auto">
|
||||
<div class="flex items-center justify-between mb-10">
|
||||
<h1 class="text-3xl font-bold">Dashboard</h1>
|
||||
<PrimaryButton label="Create Course" onClick={createCourse} />
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { supabase } from '../../functions/supabase';
|
||||
import { orgs, currentOrg } from '../../store/org';
|
||||
import { orgs, currentOrg, orgAudience } from '../../store/org';
|
||||
|
||||
export async function getOrganizations(userId) {
|
||||
const { data, error } = await supabase
|
||||
@@ -39,3 +39,42 @@ export async function getOrganizations(userId) {
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getOrgAudience(orgId) {
|
||||
// get all students who are participants in any course belonging to an org
|
||||
const { data, error } = await supabase
|
||||
.from('profile')
|
||||
.select(
|
||||
`
|
||||
id,
|
||||
fullname,
|
||||
email,
|
||||
avatar_url,
|
||||
created_at,
|
||||
groupmember!inner(
|
||||
role_id,
|
||||
group!inner(
|
||||
organization!inner(id)
|
||||
)
|
||||
)
|
||||
`
|
||||
)
|
||||
.eq('groupmember.group.organization.id', orgId)
|
||||
.eq('groupmember.role_id', 3); // is a student, tutor is 2 and admin is 1
|
||||
|
||||
console.log('data', data);
|
||||
|
||||
const audience = (data || []).map((profile) => ({
|
||||
id: profile.id,
|
||||
name: profile.fullname,
|
||||
email: profile.email,
|
||||
avatar_url: profile.avatar_url,
|
||||
date_joined: new Date(profile.created_at).toDateString(),
|
||||
}));
|
||||
orgAudience.set(audience);
|
||||
|
||||
return {
|
||||
audience: audience,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,3 +7,4 @@ export const currentOrg = writable({
|
||||
shortName: '',
|
||||
siteName: '',
|
||||
});
|
||||
export const orgAudience = writable([]);
|
||||
|
||||
Reference in New Issue
Block a user