* checkpoint * checkpoint * feat: Create free tools page * responsiveness fix * rename free-tools to tools * add slug * feat: Random name picker * quick fix * PR Fixes * PR Fixes * - adjustments * update env example * remove base url * remove base url in .env.example * fix type errors * add og images * add signup cta to /tools layout * update cta * add socials avatar * add meta tags * feat: tic tac toe (#307) * Feat: tic tac toe * PR Adjustments * feat: Implement Timed Activity Tool (#316) * chore: update verification email content * chore: landing page improvements * feat: grade exercise with AI (#296) * working on the UI of the grading * working on the grading function of the radio and checkboxes * ai grading fully implemented with dummy functions for generating scores * working on the openai response * working on the openai response * finished with the ai_grading * finished with the ai_grading * creating new migration file * working on reviews * updated the translations * improvements --------- Co-authored-by: Rotimi Best <best@classroomio.com> * feat: selfhost tinymce * fix: logo resolution error in manifest.json * feat: move from gpt3.5 to gpt-4o * feat: customize the LMS from dashboard (#304) * Done with the customization of the LMS task * generated custom_lms migration file * updated the migration file * copy improvements * update wording * made updates based on reviews,i hope i didnt miss anything * updated the translations and migration files * refactoring * disabled improvements for apps * more improvements * more custom improvements * pr refactoring --------- Co-authored-by: Rotimi Best <best@classroomio.com> * fix: CustomizeLMS not found * fix: CustomizeLms wrong path * setup * docs: update short hero tagline * debug: courses not showing on vercel * more debugging * i think this fixes it * fix: phew, clean up debug cause it works * fix: move RBS into coursecontainer on marks page * chore: cleaner way to implement redirect if role permission denied * docs: update tagline * fix: delete /org/# route * checkpoint * add reusable header component * fix: empty lesson title bug (#314) * finished the lesson title bug * made chnages based on review * Update +page.svelte --------- Co-authored-by: Rotimi Best <best@classroomio.com> * feat: add sound cdn * remove console.log * feat: course types - self paced and live class (#309) * working on the course type * trying to mark it persist * almost done here * fixed sendig emtpy options bug * created migration file * created migration file * made updates based on PR review * merge * update course type card * add redirect logic with classroomio.com/new * make new course modal only open/close with url * feat: page active state (#315) * finished the active link state * updated the active link state based on review * simplify code --------- Co-authored-by: Rotimi Best <best@classroomio.com> * add type to course card --------- Co-authored-by: Rotimi Best <best@classroomio.com> * general improvements to free tools * fix timer and styling issues --------- Co-authored-by: Rotimi Best <best@classroomio.com> Co-authored-by: Em_Dev <Chifez1@gmail.com> * update tagline for tools page * feat: Add Free Section to Landing Page (#332) * feat: Add Free Section to Landing Page * PR Fixes * refactor * PR Fixes * restructure * improve cursor UX --------- Co-authored-by: Rotimi Best <best@classroomio.com> * feat: Progress Report Tool (#329) * checkpoint * fix: corrections * finalization * improve ux of progress tool * more styling improvements * PR Fixes * PR Fixes * fix: mood bg on report * fix: generate exercise with AI bug (#331) * fix: enable lesson cascade delete (#335) * styling improvements * chore: hide course grading toggle in settings (#338) * feat: reset select in community page (#339) * Feat: Add Reset for comminity dropdown * - add translation * refactor --------- Co-authored-by: Rotimi Best <best@classroomio.com> * fix: prevent hypen at start or end of organzation or domain name (#340) * fix: adding hypen to start or end of org or domain name * fix: add org name validation to settings page * chore: remove unnecessary variable use * chore: remove error reset function * Update OrgSettings.svelte --------- Co-authored-by: Rotimi Best <best@classroomio.com> * fix: full screen * fix: pnpm version error & add top level .nvmrc (#343) * update name of tool * chore: add translations for validation messages (#345) * chore: add validation texts to locale file * feat: switch all validations from plain text to use i18n locale * feat: switch review form validations from plain text to use locale file * run translation script * chore: add translations for validation messages (#345) (#347) * chore: add translations for validation messages (#345) * chore: add validation texts to locale file * feat: switch all validations from plain text to use i18n locale * feat: switch review form validations from plain text to use locale file * run translation script --------- Co-authored-by: Iniubong Obonguko <iniubongobonguko2018@gmail.com> * PR Fixes * Bug fixes on mobile * Final bug fix * code improvements * PR Fixes * Merge Fix * PR Fixes * fix: width * code cleanup * feat: Promodo Tool (tracks tim spent) * feat: Pomodoro timer (without tracking feature) * fix: - change pause functionality to next - correct spelling of pomodoro * fix: pomodoro logo rename * styling improvements --------- Co-authored-by: Rotimi Best <best@classroomio.com> Co-authored-by: Em_Dev <Chifez1@gmail.com> Co-authored-by: Iniubong Obonguko <iniubongobonguko2018+github@gmail.com> Co-authored-by: Iniubong Obonguko <iniubongobonguko2018@gmail.com> Co-authored-by: Aditya Deshlahre <132184385+adityadeshlahre@users.noreply.github.com> * feat: Implement Bottom menu (#341) * popup logic done * popup UI first phase done * finished the menupop up for both lms and admin * finished the menupop up for both lms and admin * done * cleanup * fixed popover position * still working on the routing * i think that is it for the day * updated the menupopup currentorgdomain * rename popup to bottomMenu * refactoring --------- Co-authored-by: Rotimi Best <best@classroomio.com> * remove logout * change tagline * feat: Store todolist to localStorage (#375) * feat: Save todo to localStorage * remove fly animation to todos * feat: Progress Report avatar update (#376) * feat: Reorder Avatar list * quick fix * change avatar url * more improvements * quick background fix * fix: white background * body background fix * update lock --------- Co-authored-by: Rotimi Best <best@classroomio.com> Co-authored-by: Em_Dev <Chifez1@gmail.com> Co-authored-by: Iniubong Obonguko <iniubongobonguko2018+github@gmail.com> Co-authored-by: Iniubong Obonguko <iniubongobonguko2018@gmail.com> Co-authored-by: Aditya Deshlahre <132184385+adityadeshlahre@users.noreply.github.com>
215 lines
6.4 KiB
Svelte
215 lines
6.4 KiB
Svelte
<script>
|
|
import UserAvatarIcon from 'carbon-icons-svelte/lib/UserAvatar.svelte';
|
|
import BookIcon from 'carbon-icons-svelte/lib/Book.svelte';
|
|
import TextField from '$lib/components/Form/TextField.svelte';
|
|
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
|
|
import UploadImage from '$lib/components/UploadImage/index.svelte';
|
|
import { supabase } from '$lib/utils/functions/supabase';
|
|
import { user, profile } from '$lib/utils/store/user';
|
|
|
|
export let data;
|
|
const { profileId } = data;
|
|
|
|
let avatar;
|
|
let loading = false;
|
|
let currentProfile = {};
|
|
let isOwner = false;
|
|
let initialValueOfUserName, initialValueOfFullName, initialValueOfAvatar;
|
|
|
|
async function getProfile(profileId) {
|
|
loading = true;
|
|
// Get user profile
|
|
|
|
// Check if user has profile
|
|
let {
|
|
data: profileData,
|
|
error,
|
|
status
|
|
} = await supabase.from('profile').select(`*`).eq('id', profileId).single();
|
|
|
|
if (error && !profileData && status === 406 && $user.currentSession) {
|
|
// Not found
|
|
} else if (profileData) {
|
|
// Profile exists, go to profile page
|
|
currentProfile = profileData;
|
|
initialValueOfUserName = currentProfile.username;
|
|
initialValueOfFullName = currentProfile.fullname;
|
|
}
|
|
|
|
loading = false;
|
|
}
|
|
|
|
async function updateProfile() {
|
|
try {
|
|
loading = true;
|
|
|
|
const updates = {
|
|
fullname: currentProfile.fullname,
|
|
username: currentProfile.username
|
|
};
|
|
|
|
if (avatar) {
|
|
const filename = `user/${currentProfile.username + Date.now()}.webp`;
|
|
|
|
const { data } = await supabase.storage.from('avatars').upload(filename, avatar, {
|
|
cacheControl: '3600',
|
|
upsert: false
|
|
});
|
|
|
|
if (data) {
|
|
const { data: response } = supabase.storage.from('avatars').getPublicUrl(filename);
|
|
|
|
updates.avatar_url = response.publicUrl;
|
|
currentProfile.avatar_url = response.publicUrl;
|
|
}
|
|
avatar = undefined;
|
|
}
|
|
|
|
let { error } = await supabase.from('profile').update(updates).match({ id: profileId });
|
|
|
|
if (isOwner) {
|
|
profile.update((_profile) => ({
|
|
..._profile,
|
|
...updates
|
|
}));
|
|
}
|
|
|
|
if (error) throw error;
|
|
} catch (error) {
|
|
alert(error.message);
|
|
loading = false;
|
|
} finally {
|
|
loading = false;
|
|
|
|
initialValueOfUserName = currentProfile.username;
|
|
initialValueOfFullName = currentProfile.fullname;
|
|
}
|
|
}
|
|
|
|
$: isDirty =
|
|
avatar ||
|
|
initialValueOfUserName !== currentProfile.username ||
|
|
initialValueOfFullName !== currentProfile.fullname;
|
|
$: isOwner = $profile.id === profileId;
|
|
$: getProfile(profileId);
|
|
|
|
$: if (avatar) {
|
|
updateProfile();
|
|
}
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>Profile of {currentProfile.username}</title>
|
|
</svelte:head>
|
|
|
|
<section class="root w-11/12 mt-3 m-auto flex items-start justify-between flex-col lg:flex-row">
|
|
{#if currentProfile.id}
|
|
<div class="w-full lg:w-1/4 flex items-center flex-col">
|
|
<!-- <img
|
|
alt={currentProfile.username}
|
|
src={currentProfile.avatar_url}
|
|
height="260"
|
|
width="260"
|
|
class="rounded-full bg-primary-100 mb-4"
|
|
/> -->
|
|
<UploadImage bind:avatar src={currentProfile.avatar_url} widthHeight="w-60 h-60" />
|
|
|
|
{#if isOwner}
|
|
<TextField
|
|
label="Full name"
|
|
bind:value={currentProfile.fullname}
|
|
className="w-60 mb-4"
|
|
inputClassName="rounded-md"
|
|
/>
|
|
<TextField
|
|
label="Username"
|
|
bind:value={currentProfile.username}
|
|
className="w-60 mb-4"
|
|
inputClassName="rounded-md"
|
|
/>
|
|
<TextField
|
|
label="Email"
|
|
bind:value={currentProfile.email}
|
|
className="w-60 mb-4"
|
|
inputClassName="rounded-md"
|
|
isDisabled={true}
|
|
/>
|
|
|
|
{#if isDirty}
|
|
<PrimaryButton
|
|
label={loading ? 'Updating...' : 'Update profile'}
|
|
onClick={updateProfile}
|
|
isDisabled={loading}
|
|
/>
|
|
{/if}
|
|
{:else}
|
|
<h3 class="dark:text-white text-xl">{currentProfile.username}</h3>
|
|
{/if}
|
|
</div>
|
|
|
|
<div class="flex-grow" />
|
|
<div class="flex-grow flex flex-wrap mx-3 w-3/5">
|
|
<div class="mb-3 w-full">
|
|
<h3 class="dark:text-white font-bold text-md m-0">Organizations</h3>
|
|
<p class="dark:text-white text-gray-500 text-sm">This are the organizations you work at</p>
|
|
|
|
<div class="hidden my-3 py-3 px-4 border shadow-sm rounded-md">
|
|
<h4 class="dark:text-white m-0 font-normal">
|
|
<a class="text-primary-700 font-bold" href="/courses"> CitiBim </a>
|
|
</h4>
|
|
<p class="dark:text-white text-gray-500">
|
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Non aliquam tenetur magnam.
|
|
Alias cumque quaerat expedita dolores placeat laboriosam culpa, suscipit veritatis
|
|
adipisci eius magni obcaecati. Sequi doloremque blanditiis earum.
|
|
</p>
|
|
<div class="mt-2 flex items-center">
|
|
<span class="flex mr-2 items-center">
|
|
<UserAvatarIcon size={16} class="mr-2" /> 5
|
|
</span>
|
|
|
|
<span class="flex mr-2 items-center">
|
|
<BookIcon size={16} class="mr-2" /> 5
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="hidden my-2 py-3 px-4 border shadow-sm rounded-md">
|
|
<h4 class="dark:text-white m-0 font-normal">
|
|
<a class="text-primary-700 font-bold" href="/courses"> Climate Change Group </a>
|
|
</h4>
|
|
<p class="dark:text-white text-gray-500">
|
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo quasi autem quo possimus
|
|
illum consequuntur repudiandae nobis error, porro
|
|
</p>
|
|
<div class="mt-2 flex items-center">
|
|
<span class="flex mr-2 items-center">
|
|
<UserAvatarIcon size={16} class="mr-2" /> 30
|
|
</span>
|
|
|
|
<span class="flex mr-2 items-center">
|
|
<BookIcon size={16} class="mr-2" /> 3
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- {:else if loading}
|
|
<Box>
|
|
<Chasing size="60" color="#ff3e00" unit="px" duration="1s" />
|
|
</Box>
|
|
{:else}
|
|
<Box>
|
|
<div>
|
|
<Search32 />
|
|
</div>
|
|
<h3 class="dark:text-white text-xxl">Profile not found</h3>
|
|
</Box> -->
|
|
{/if}
|
|
</section>
|
|
|
|
<style>
|
|
.root {
|
|
max-width: 1204px;
|
|
}
|
|
</style>
|