CLASSROOMIO-T-115: Fetch data on server CLASSROOMIO-T-115: Add dynamic debug orgs, handle not found orgs, add 404 to public route CLASSROOMIO-T-115:Automacally add prefix to the footer input CLASSROOMIO-T-115:Implemented the video to also play youtube videos Merge branch 'CLASSROOMIO-T-115' of https://gitlab.com/thenextgreat/classroomio into CLASSROOMIO-T-115 CLASSROOMIO-T-115:Implemented the video to also play youtube videos CLASSROOMIO-T-115:Still woking on the landing page UI CLASSROOMIO-T-115: Some improvements CLASSROOMIO-T-115:Working on the landing page UI Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio Merge branch 'main' of https://gitlab.com/thenextgreat/classroomio CLASSROOMIO-T-27: Review Section for Instructors on landing page CLASSROOMIO-T-27: Remove unused variable Merge branch 'CLASSROOMIO-T-27' of https://gitlab.com/thenextgreat/classroomio into CLASSROOMIO-T-27 CLASSROOMIO-T-27: Complete reviews functionality CLASSROOMIO-T-27: Review Render Update CLASSROOMIO-T-27: - Resolved Feedbacks CLASSROOMIO-T-27: Fixed Ratings Data CLASSROOMIO-T-27: - Added Ratings Svg - Fixed avatar_url feedback CLASSROOMIO-T-27: Import Adjustment CLASSROOMIO-T-27: Code Review CLASSROOM-T-27: Added Add Review Functionality CLASSROOMIO-T-27: - Unresolved Review - Enhance Code Redability CLASSROOMIO-T-27: Completed the delete functionality CLASSROOMIO-T-27: Hide/Show functionality CLASSROOMIO-T-27: Double Quotation Update CLASSROOMIO-T-27: Testing toggle functinality CLASSROOMIO-T-27: Added the icons CLASSROOMIO-T-27: Completion of the hide/show functionality CLASSROOMIO-T-27: Display the store data on the review page for styling CLASSROOMIO-T-27: Styling of the review component & connecting it's data CLASSROOMIO-T-27: - Add ReviewsForm - Completion of the Reviews Form Structure/Styling CLASSROOMIO-T-27: Added a reviews modal CLASSROOMIO-T-27: Logic update for review section CLASSROOMIO-T-50: Logic for overlapping reviews CLASSROOMIO-T-27: - Completion of the structure & styling with mock data. - Addition of custom ratings assets CLASSROOMIO-T-27: - Review Section Code Structure - Import Profile Picture Assets Co-authored-by: Rotimi Best <rotimiibitoyeemma@gmail.com> Co-authored-by: Tunji Adeyemi <tunji@digdippa.com> Co-authored-by: tunny17 <tvnji17@gmail.com> Merge-request: CLASSROOMIO-MR-22 Merged-by: Best Admin <best@digdippa.com> CLASSROOMIO-T-62: Dark Mode Bug Fix CLASSROOMIO-T-62: Delete Unused class CLASSROOMIO-T-62: Dark Mode Bug Fix Co-authored-by: Tunji Adeyemi <tunji@digdippa.com> Merge-request: CLASSROOMIO-MR-23 Merged-by: Best Admin <best@digdippa.com> Co-authored-by: Ifeanyi Nwosu <ifeanyi@digdippa.com> Co-authored-by: Rotimi Best <rotimiibitoyeemma@gmail.com> Co-authored-by: Tunji Adeyemi <tunji@digdippa.com> Co-authored-by: tunny17 <tvnji17@gmail.com> Merge-request: CLASSROOMIO-MR-53 Merged-by: Best Admin <best@digdippa.com>
454 lines
14 KiB
Svelte
454 lines
14 KiB
Svelte
<script lang="ts">
|
|
import { Grid, Row, Column } from 'carbon-components-svelte';
|
|
import TrashCan from 'carbon-icons-svelte/lib/TrashCan.svelte';
|
|
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
|
import IconButton from '$lib/components/IconButton/index.svelte';
|
|
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
|
|
import SectionTitle from '../SectionTitle.svelte';
|
|
import { Toggle } from 'carbon-components-svelte';
|
|
import TextField from '$lib/components/Form/TextField.svelte';
|
|
import TextArea from '$lib/components/Form/TextArea.svelte';
|
|
import { currentOrg } from '$lib/utils/store/org';
|
|
import { getSupabase } from '$lib/utils/functions/supabase';
|
|
import { snackbarStore } from '$lib/components/Snackbar/store';
|
|
import { SNACKBAR_SEVERITY } from '$lib/components/Snackbar/constants';
|
|
import { FileUploader } from 'carbon-components-svelte';
|
|
import { landingPageSettings } from './store';
|
|
import type { OrgLandingPageJson } from './store';
|
|
|
|
let files: File[] = [];
|
|
let imageBuffer: File;
|
|
let uploadingImage = false;
|
|
let isSaving = false;
|
|
let creatingNewQuestion = false;
|
|
|
|
const supabase = getSupabase();
|
|
|
|
let newQuestion = {
|
|
title: '',
|
|
content: ''
|
|
};
|
|
|
|
function createNewFaq() {
|
|
newQuestion = {
|
|
title: '',
|
|
content: ''
|
|
};
|
|
creatingNewQuestion = true;
|
|
}
|
|
|
|
function saveNewFAQ() {
|
|
if (newQuestion.title !== '' && newQuestion.content !== '') {
|
|
$landingPageSettings.faq.questions = [
|
|
...$landingPageSettings.faq.questions,
|
|
{
|
|
id: new Date().getTime(),
|
|
title: newQuestion.title,
|
|
content: newQuestion.content
|
|
}
|
|
];
|
|
creatingNewQuestion = false;
|
|
}
|
|
}
|
|
|
|
function cancelNewFAQ() {
|
|
creatingNewQuestion = false;
|
|
}
|
|
|
|
function deleteFaq(id: number) {
|
|
let faqs = $landingPageSettings.faq.questions;
|
|
const filteredFaq = faqs.filter((faq) => faq.id !== id);
|
|
$landingPageSettings.faq.questions = filteredFaq;
|
|
}
|
|
|
|
const uploadImage = async (image: File) => {
|
|
if (image) {
|
|
const filename = `landingpage/${Date.now()}` + image.name;
|
|
const { data } = await supabase.storage.from('avatars').upload(filename, image, {
|
|
cacheControl: '3600',
|
|
upsert: false
|
|
});
|
|
|
|
if (data) {
|
|
const { data: response } = await supabase.storage.from('avatars').getPublicUrl(filename);
|
|
|
|
$landingPageSettings.aboutUs.imageUrl = response.publicUrl;
|
|
uploadingImage = false;
|
|
}
|
|
}
|
|
};
|
|
|
|
const onFileSelected = (image: File) => {
|
|
uploadingImage = true;
|
|
let reader = new FileReader();
|
|
reader.readAsDataURL(image);
|
|
reader.onload = (e) => {
|
|
imageBuffer = image;
|
|
|
|
uploadImage(image);
|
|
};
|
|
};
|
|
|
|
const checkPrefix = (inputValue: string) => {
|
|
if (!inputValue) return;
|
|
|
|
if (inputValue.trim() !== '') {
|
|
if (!inputValue.startsWith('https://')) {
|
|
inputValue = 'https://' + inputValue;
|
|
}
|
|
}
|
|
return inputValue;
|
|
};
|
|
async function handleSave() {
|
|
isSaving = true;
|
|
$landingPageSettings.footer.twitter = checkPrefix($landingPageSettings.footer.twitter);
|
|
$landingPageSettings.footer.linkedin = checkPrefix($landingPageSettings.footer.linkedin);
|
|
$landingPageSettings.footer.facebook = checkPrefix($landingPageSettings.footer.facebook);
|
|
console.log($landingPageSettings.footer.twitter);
|
|
const { data, error } = await supabase
|
|
.from('organization')
|
|
.update({ landingpage: $landingPageSettings })
|
|
.match({ id: $currentOrg.id });
|
|
|
|
if (error) {
|
|
let message = error?.message || 'Please try again';
|
|
|
|
$snackbarStore.open = true;
|
|
$snackbarStore.message = `Update failed: ${message}`;
|
|
$snackbarStore.severity = SNACKBAR_SEVERITY.ERROR;
|
|
} else {
|
|
$currentOrg.landingpage = $landingPageSettings;
|
|
$snackbarStore.open = true;
|
|
$snackbarStore.message = 'Saved successful';
|
|
$snackbarStore.severity = SNACKBAR_SEVERITY.SUCCESS;
|
|
}
|
|
|
|
isSaving = false;
|
|
}
|
|
|
|
function setDefault(landingpage: OrgLandingPageJson) {
|
|
if (landingpage && Object.keys(landingpage).length) {
|
|
$landingPageSettings = landingpage;
|
|
}
|
|
}
|
|
|
|
$: setDefault($currentOrg?.landingpage);
|
|
</script>
|
|
|
|
<Grid class="border-c rounded border-gray-200 w-full mt-5 relative">
|
|
<Row class="py-7 border-bottom-c">
|
|
<Column sm={2} md={2} lg={4}>
|
|
<SectionTitle>Landing Page</SectionTitle>
|
|
<Toggle bind:toggled={$landingPageSettings.header.show} size="sm">
|
|
<span slot="labelA" style="color: gray">Hide section</span>
|
|
<span slot="labelB" style="color: gray">Show section</span>
|
|
</Toggle>
|
|
</Column>
|
|
<Column sm={2} md={6} lg={8}>
|
|
<TextField
|
|
label="Title"
|
|
placeholder="Write your title here"
|
|
bind:value={$landingPageSettings.header.title}
|
|
className="mb-5"
|
|
/>
|
|
<TextField
|
|
label="Title-Highlight"
|
|
placeholder="Write your titlehighlight here"
|
|
className="mb-5"
|
|
bind:value={$landingPageSettings.header.titleHighlight}
|
|
/>
|
|
|
|
<TextArea
|
|
label="Subtitle"
|
|
labelClassName="font-light"
|
|
placeholder="Write your subtitle here"
|
|
className="mb-5"
|
|
bind:value={$landingPageSettings.header.subtitle}
|
|
/>
|
|
|
|
<SectionTitle>Actions</SectionTitle>
|
|
<TextField
|
|
label="Label"
|
|
placeholder="Write your label here"
|
|
className="mt-3 mb-5"
|
|
bind:value={$landingPageSettings.header.action.label}
|
|
/>
|
|
<div class="gap-2 mb-5">
|
|
<TextField
|
|
label="Link"
|
|
placeholder="Write your link here"
|
|
bind:value={$landingPageSettings.header.action.link}
|
|
/>
|
|
<Toggle bind:toggled={$landingPageSettings.header.action.redirect} size="sm">
|
|
<span slot="labelA" style="color: gray">No redirect</span>
|
|
<span slot="labelB" style="color: gray">Redirect</span>
|
|
</Toggle>
|
|
</div>
|
|
<SectionTitle>Video</SectionTitle>
|
|
<div class="gap-2 mt-3 mb-5">
|
|
<TextField
|
|
label="Link"
|
|
placeholder="Write your video link here"
|
|
bind:value={$landingPageSettings.header.video.link}
|
|
/>
|
|
<Toggle bind:toggled={$landingPageSettings.header.video.show} size="sm">
|
|
<span slot="labelA" style="color: gray">Hide Video</span>
|
|
<span slot="labelB" style="color: gray">Show Video</span>
|
|
</Toggle>
|
|
</div>
|
|
</Column>
|
|
</Row>
|
|
|
|
<Row class="py-7 border-bottom-c">
|
|
<Column sm={2} md={2} lg={4}
|
|
><SectionTitle>About</SectionTitle>
|
|
<Toggle bind:toggled={$landingPageSettings.aboutUs.show} size="sm">
|
|
<span slot="labelA" style="color: gray">Hide section</span>
|
|
<span slot="labelB" style="color: gray">Show section</span>
|
|
</Toggle></Column
|
|
>
|
|
<Column sm={2} md={6} lg={8}>
|
|
<TextField
|
|
label="Title"
|
|
placeholder="Write your title here"
|
|
bind:value={$landingPageSettings.aboutUs.title}
|
|
className="mb-5"
|
|
/>
|
|
|
|
<TextArea
|
|
label="Content"
|
|
labelClassName="font-light"
|
|
placeholder="Write your Content here"
|
|
className="mb-5"
|
|
bind:value={$landingPageSettings.aboutUs.content}
|
|
/>
|
|
|
|
<div>
|
|
<FileUploader
|
|
status={uploadingImage ? 'uploading' : 'complete'}
|
|
buttonLabel="Select file"
|
|
labelTitle="Upload an image"
|
|
class="flex-col items-start gap-2 w-full"
|
|
accept={['.jpg', '.jpeg', '.png']}
|
|
bind:files
|
|
on:change={(file) => onFileSelected(file?.detail?.[0])}
|
|
/>
|
|
{#if $landingPageSettings.aboutUs.imageUrl}
|
|
<img
|
|
alt="About us"
|
|
src={$landingPageSettings.aboutUs.imageUrl}
|
|
class="mt-2 rounded-md w-full"
|
|
/>
|
|
{/if}
|
|
</div>
|
|
</Column>
|
|
</Row>
|
|
|
|
<Row class="py-7 border-bottom-c">
|
|
<Column sm={2} md={2} lg={4}
|
|
><SectionTitle>Courses</SectionTitle>
|
|
<Toggle bind:toggled={$landingPageSettings.courses.show} size="sm">
|
|
<span slot="labelA" style="color: gray">Hide section</span>
|
|
<span slot="labelB" style="color: gray">Show section</span>
|
|
</Toggle>
|
|
</Column>
|
|
<Column sm={2} md={6} lg={8}>
|
|
<TextField
|
|
label="Title"
|
|
placeholder="Write your title here"
|
|
bind:value={$landingPageSettings.courses.title}
|
|
/>
|
|
<TextField
|
|
label="Title-Highlight"
|
|
placeholder="Write your title highlight here"
|
|
bind:value={$landingPageSettings.courses.titleHighlight}
|
|
/>
|
|
<TextArea
|
|
label="Subtitle"
|
|
labelClassName="font-light"
|
|
placeholder="Write your subtitle here"
|
|
bind:value={$landingPageSettings.courses.subtitle}
|
|
/>
|
|
</Column>
|
|
</Row>
|
|
|
|
<Row class="py-7 border-bottom-c">
|
|
<Column sm={2} md={2} lg={4}
|
|
><SectionTitle>Frequently Asked Questions</SectionTitle>
|
|
<Toggle bind:toggled={$landingPageSettings.faq.show} size="sm">
|
|
<span slot="labelA" style="color: gray">Hide section</span>
|
|
<span slot="labelB" style="color: gray">Show section</span>
|
|
</Toggle>
|
|
</Column>
|
|
<Column sm={2} md={6} lg={8}>
|
|
<TextField
|
|
label="Title"
|
|
placeholder="Write your title here"
|
|
bind:value={$landingPageSettings.faq.title}
|
|
className="mb-5"
|
|
/>
|
|
{#each $landingPageSettings.faq.questions as item (item.id)}
|
|
<div class="mb-3">
|
|
<TextField
|
|
label="Question"
|
|
placeholder="Write your question here"
|
|
bind:value={item.title}
|
|
className="mb-5"
|
|
/>
|
|
<TextArea
|
|
label="Answer"
|
|
labelClassName="font-light"
|
|
placeholder="Write your answer here"
|
|
bind:value={item.content}
|
|
className="mb-5"
|
|
/>
|
|
<IconButton onClick={() => deleteFaq(item.id)}>
|
|
<TrashCan size={24} class="fill-red-700" />
|
|
</IconButton>
|
|
</div>
|
|
{/each}
|
|
{#if creatingNewQuestion}
|
|
<TextField
|
|
label="Question"
|
|
placeholder="Write your question here"
|
|
bind:value={newQuestion.title}
|
|
className="mb-5"
|
|
/>
|
|
<TextArea
|
|
label="Answer"
|
|
labelClassName="font-light"
|
|
placeholder="Write your answer here"
|
|
bind:value={newQuestion.content}
|
|
className="mb-5"
|
|
/>
|
|
<div class="flex items-center gap-2">
|
|
<PrimaryButton variant={VARIANTS.OUTLINED} label="Save" onClick={saveNewFAQ} />
|
|
<PrimaryButton variant={VARIANTS.OUTLINED} label="Cancel" onClick={cancelNewFAQ} />
|
|
</div>
|
|
{:else}
|
|
<PrimaryButton variant={VARIANTS.OUTLINED} label="Add New Faq" onClick={createNewFaq} />
|
|
{/if}
|
|
</Column>
|
|
</Row>
|
|
|
|
<Row class="py-7 border-bottom-c">
|
|
<Column sm={2} md={2} lg={4}
|
|
><SectionTitle>Contact us</SectionTitle>
|
|
<Toggle bind:toggled={$landingPageSettings.contact.show} size="sm">
|
|
<span slot="labelA" style="color: gray">Hide section</span>
|
|
<span slot="labelB" style="color: gray">Show section</span>
|
|
</Toggle>
|
|
</Column>
|
|
<Column sm={2} md={6} lg={8}>
|
|
<TextField
|
|
label="Title"
|
|
placeholder="Write your title here"
|
|
bind:value={$landingPageSettings.contact.title}
|
|
className="mb-5"
|
|
/>
|
|
<TextField
|
|
label="Title-highlight"
|
|
labelClassName="font-light"
|
|
placeholder="Write your title highlight here"
|
|
className="mb-5"
|
|
bind:value={$landingPageSettings.contact.titleHighlight}
|
|
/>
|
|
<TextArea
|
|
label="Subtitle"
|
|
labelClassName="font-light"
|
|
placeholder="Write your subtitle here"
|
|
className="mt-3 mb-5"
|
|
bind:value={$landingPageSettings.contact.subtitle}
|
|
/>
|
|
<TextField
|
|
label="Phone number"
|
|
placeholder="Write your phone number here"
|
|
className="mt-3 mb-5"
|
|
bind:value={$landingPageSettings.contact.phone}
|
|
/>
|
|
<TextField
|
|
label="Email"
|
|
placeholder="Write your email here"
|
|
className="mt-3 mb-5"
|
|
bind:value={$landingPageSettings.contact.email}
|
|
/>
|
|
</Column>
|
|
</Row>
|
|
|
|
<Row class="py-7 border-bottom-c">
|
|
<Column sm={2} md={2} lg={4}
|
|
><SectionTitle>Mailing List</SectionTitle>
|
|
<Toggle bind:toggled={$landingPageSettings.mailinglist.show} size="sm">
|
|
<span slot="labelA" style="color: gray">Hide section</span>
|
|
<span slot="labelB" style="color: gray">Show section</span>
|
|
</Toggle>
|
|
</Column>
|
|
<Column sm={2} md={6} lg={8}>
|
|
<TextField
|
|
label="Title"
|
|
placeholder="Write your title here"
|
|
bind:value={$landingPageSettings.mailinglist.title}
|
|
className="mb-5"
|
|
/>
|
|
<TextArea
|
|
label="Subtitle"
|
|
labelClassName="font-light"
|
|
placeholder="Write your subtitle here"
|
|
className="mb-5"
|
|
bind:value={$landingPageSettings.mailinglist.subtitle}
|
|
/>
|
|
|
|
<TextField
|
|
label="Button-label"
|
|
placeholder="Write your label here"
|
|
className="mb-5"
|
|
bind:value={$landingPageSettings.mailinglist.buttonLabel}
|
|
/>
|
|
</Column>
|
|
</Row>
|
|
|
|
<Row class="py-7 border-bottom-c">
|
|
<Column sm={2} md={2} lg={4}
|
|
><SectionTitle>Footer</SectionTitle>
|
|
<Toggle bind:toggled={$landingPageSettings.footer.show} size="sm">
|
|
<span slot="labelA" style="color: gray">Hide section</span>
|
|
<span slot="labelB" style="color: gray">Show section</span>
|
|
</Toggle>
|
|
</Column>
|
|
<Column sm={2} md={6} lg={8}>
|
|
<TextField
|
|
label="Facebook"
|
|
placeholder="Write your Facebook link here"
|
|
bind:value={$landingPageSettings.footer.facebook}
|
|
className="mb-5"
|
|
/>
|
|
<!-- <TextField
|
|
label="Instagram"
|
|
placeholder="Write your Instagram link here"
|
|
className="mb-5"
|
|
bind:value={$landingPageSettings.footer.instagram}
|
|
/> -->
|
|
<TextField
|
|
label="Twitter"
|
|
placeholder="Write your Twitter link here"
|
|
className="mb-5"
|
|
bind:value={$landingPageSettings.footer.twitter}
|
|
/>
|
|
<TextField
|
|
label="Linkedin"
|
|
placeholder="Write your Linkedin link here"
|
|
className="mb-5"
|
|
bind:value={$landingPageSettings.footer.linkedin}
|
|
/>
|
|
</Column>
|
|
</Row>
|
|
<Row class="p-5 w-full flex items-center justify-center">
|
|
<PrimaryButton
|
|
label="Save Changes"
|
|
isLoading={isSaving}
|
|
isDisabled={isSaving}
|
|
onClick={handleSave}
|
|
/>
|
|
</Row>
|
|
</Grid>
|