[+] Course page
This commit is contained in:
+17
-2
@@ -10,7 +10,13 @@ $c-green: rgb(88, 204, 2)
|
|||||||
$c-green-shadow: rgb(88, 167, 0)
|
$c-green-shadow: rgb(88, 167, 0)
|
||||||
$c-red: rgb(255, 69, 58)
|
$c-red: rgb(255, 69, 58)
|
||||||
$c-red-shadow: darken($c-red, 10%)
|
$c-red-shadow: darken($c-red, 10%)
|
||||||
|
$c-gold: rgb(255, 200, 0)
|
||||||
|
$c-gold-flare: rgb(251, 233, 2)
|
||||||
|
$c-gold-shadow: rgb(221, 164, 11)
|
||||||
|
$c-gold-text: rgb(195, 126, 11)
|
||||||
$c-white-shadow: rgb(222, 222, 222)
|
$c-white-shadow: rgb(222, 222, 222)
|
||||||
|
$c-gray: rgb(229, 229, 229)
|
||||||
|
$c-gray-shadow: rgb(175, 175, 175)
|
||||||
$border-radius: 16px
|
$border-radius: 16px
|
||||||
$shadow-width: 0 4px 0
|
$shadow-width: 0 4px 0
|
||||||
|
|
||||||
@@ -78,6 +84,12 @@ button.white
|
|||||||
&.no-shadow
|
&.no-shadow
|
||||||
border-width: 2px
|
border-width: 2px
|
||||||
|
|
||||||
|
.box.green
|
||||||
|
border: none
|
||||||
|
background-color: $c-green
|
||||||
|
box-shadow: $shadow-width $c-green-shadow
|
||||||
|
color: white
|
||||||
|
|
||||||
input
|
input
|
||||||
@extend .box
|
@extend .box
|
||||||
transition: all 0.2s ease-in-out
|
transition: all 0.2s ease-in-out
|
||||||
@@ -109,13 +121,16 @@ h2
|
|||||||
|
|
||||||
gap: 1em
|
gap: 1em
|
||||||
width: 100%
|
width: 100%
|
||||||
height: 100%
|
|
||||||
|
|
||||||
&.non-center
|
&.non-center
|
||||||
justify-content: flex-start
|
justify-content: flex-start
|
||||||
|
|
||||||
|
&.gap2
|
||||||
|
gap: 2em
|
||||||
|
|
||||||
.page-pad
|
.page-pad
|
||||||
padding: 2em 1em
|
padding: 2em 1em
|
||||||
|
height: 100%
|
||||||
|
|
||||||
.navbar
|
.navbar
|
||||||
position: fixed
|
position: fixed
|
||||||
@@ -201,4 +216,4 @@ h2
|
|||||||
.message.other
|
.message.other
|
||||||
align-self: flex-start
|
align-self: flex-start
|
||||||
background-color: $c-green
|
background-color: $c-green
|
||||||
border-radius: 0 20px 20px 20px
|
border-radius: 0 20px 20px 20px
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export interface Lang {
|
|||||||
icon: string
|
icon: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const possibleLangs = [
|
export const possibleLangs: Lang[] = [
|
||||||
{name: 'Mandarin Chinese', code: 'zh', icon: MandarinChinese},
|
{name: 'Mandarin Chinese', code: 'zh', icon: MandarinChinese},
|
||||||
{name: 'Japanese', code: 'ja', icon: Japanese},
|
{name: 'Japanese', code: 'ja', icon: Japanese},
|
||||||
{name: 'English', code: 'en', icon: English},
|
{name: 'English', code: 'en', icon: English},
|
||||||
@@ -53,17 +53,31 @@ export function isLoggedIn()
|
|||||||
return !!db.user
|
return !!db.user
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLanguage(username: string)
|
|
||||||
{
|
|
||||||
const users = JSON.parse(db.users)
|
|
||||||
return users[username].language
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getUsername()
|
export function getUsername()
|
||||||
{
|
{
|
||||||
return db.user
|
return db.user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getLanguage(): Lang
|
||||||
|
{
|
||||||
|
const users = JSON.parse(db.users)
|
||||||
|
const lang = users[getUsername()].language
|
||||||
|
if (!lang)
|
||||||
|
{
|
||||||
|
alert('No language set, logging out')
|
||||||
|
logout()
|
||||||
|
window.location.href = '/'
|
||||||
|
}
|
||||||
|
const lang_obj = possibleLangs.find(l => l.name === lang)!
|
||||||
|
if (!lang_obj)
|
||||||
|
{
|
||||||
|
alert(`Invalid language set: ${lang}, logging out`)
|
||||||
|
logout()
|
||||||
|
window.location.href = '/'
|
||||||
|
}
|
||||||
|
return lang_obj
|
||||||
|
}
|
||||||
|
|
||||||
export interface CharacterChatCreationRequest
|
export interface CharacterChatCreationRequest
|
||||||
{
|
{
|
||||||
character: string;
|
character: string;
|
||||||
@@ -78,12 +92,12 @@ export interface CharacterChatCreationResponse
|
|||||||
|
|
||||||
export async function startFictionalChat(character: string): Promise<CharacterChatCreationResponse> {
|
export async function startFictionalChat(character: string): Promise<CharacterChatCreationResponse> {
|
||||||
const currUser = getUsername();
|
const currUser = getUsername();
|
||||||
const language = getLanguage(currUser);
|
const language = getLanguage();
|
||||||
|
|
||||||
const request: CharacterChatCreationRequest = {
|
const request: CharacterChatCreationRequest = {
|
||||||
character: character,
|
character: character,
|
||||||
user_name: currUser,
|
user_name: currUser,
|
||||||
language: language
|
language: language.name
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await fetch(`${backendUrl}/character-chat`, {
|
const response = await fetch(`${backendUrl}/character-chat`, {
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
@import "../index"
|
||||||
|
|
||||||
|
.course-button
|
||||||
|
@extend button
|
||||||
|
@extend .green
|
||||||
|
|
||||||
|
box-shadow: 0 8px 0 $c-green-shadow
|
||||||
|
|
||||||
|
width: 70px
|
||||||
|
height: 60px
|
||||||
|
border-radius: 50%
|
||||||
|
|
||||||
|
display: flex
|
||||||
|
justify-content: center
|
||||||
|
align-items: center
|
||||||
|
font-size: 5em
|
||||||
|
overflow: hidden
|
||||||
|
|
||||||
|
&.gray
|
||||||
|
background: $c-gray
|
||||||
|
color: $c-gray-shadow
|
||||||
|
box-shadow: 0 8px 0 $c-gray-shadow
|
||||||
|
|
||||||
|
&.gold
|
||||||
|
background: $c-gold
|
||||||
|
color: $c-gold-text
|
||||||
|
box-shadow: 0 8px 0 $c-gold-shadow
|
||||||
|
|
||||||
|
|
||||||
@@ -1,14 +1,66 @@
|
|||||||
import NavBar from "../components/NavBar"
|
import NavBar from "../components/NavBar"
|
||||||
|
import {Icon} from "@iconify/react";
|
||||||
|
import {getLanguage, isLoggedIn} from "../logic/sdk";
|
||||||
|
import React from "react";
|
||||||
|
import "./Course.sass"
|
||||||
|
|
||||||
export default function Course() {
|
function CourseButton(props: {state: 'active' | 'locked' | 'completed', index: number})
|
||||||
|
{
|
||||||
|
let cs = 'course-button ' + {active: 'green', locked: 'gray', completed: 'gold'}[props.state];
|
||||||
|
|
||||||
return (
|
const icon = {active: 'solar:star-bold', locked: 'solar:lock-bold', completed: 'mingcute:check-fill'}[props.state];
|
||||||
<div className="v-layout p-10">
|
|
||||||
<div className="flex flex-col flex-1">
|
// Parameters for the sin wave
|
||||||
<h1>Course Page</h1>
|
const amplitude = 50; // Change this value to adjust the wave's height
|
||||||
</div>
|
const frequency = 1; // Change this value to adjust the wave's frequency
|
||||||
<NavBar />
|
|
||||||
|
// Calculate the horizontal translation
|
||||||
|
const translateXValue = amplitude * Math.sin(props.index * frequency);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={cs} style={{transform: `translateX(${translateXValue}px)`}}>
|
||||||
|
<Icon icon={icon}/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default function Course()
|
||||||
|
{
|
||||||
|
if (!isLoggedIn())
|
||||||
|
{
|
||||||
|
window.location.href = '/login';
|
||||||
|
return <div></div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get language
|
||||||
|
const lang = getLanguage();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="v-layout page-pad non-center">
|
||||||
|
<div className="flex items-center justify-between font-bold">
|
||||||
|
<img src={lang.icon} alt={lang.name} className="max-w-[50px]"/>
|
||||||
|
<div className="flex items-center text-red-500 text-lg gap-2">
|
||||||
|
<Icon icon="bi:fire" className="text-xl"/>
|
||||||
|
<span>1</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
|
<div className="box green">
|
||||||
|
<div>Chapter 1, Section 1</div>
|
||||||
|
<div className="font-bold">Say hello and goodbye, use numbers</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
}
|
<div className="v-layout non-center items-center gap2">
|
||||||
|
<CourseButton state={'completed'} index={0}/>
|
||||||
|
<CourseButton state={'active'} index={1}/>
|
||||||
|
<CourseButton state={'locked'} index={2}/>
|
||||||
|
<CourseButton state={'locked'} index={3}/>
|
||||||
|
<CourseButton state={'locked'} index={4}/>
|
||||||
|
<CourseButton state={'locked'} index={5}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<NavBar/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ export default function Profile() {
|
|||||||
<div className="flex flex-col flex-1 h-full">
|
<div className="flex flex-col flex-1 h-full">
|
||||||
<h1>Profile</h1>
|
<h1>Profile</h1>
|
||||||
<h2>Username: {username}</h2>
|
<h2>Username: {username}</h2>
|
||||||
<h2>Currently Learning: {getLanguage(username)}</h2>
|
<h2>Currently Learning: {getLanguage().name}</h2>
|
||||||
<button className="red mt-auto mb-12" onClick={() => handleLougout()}>Logout</button>
|
<button className="red mt-auto mb-12" onClick={() => handleLougout()}>Logout</button>
|
||||||
</div>
|
</div>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export default function Review() {
|
|||||||
|
|
||||||
const writtenReview = ["Questions", "Vocabulary"];
|
const writtenReview = ["Questions", "Vocabulary"];
|
||||||
const verbalReview = ["Questions", "Pronunciation"];
|
const verbalReview = ["Questions", "Pronunciation"];
|
||||||
const language = getLanguage(getUsername());
|
const language = getLanguage().name;
|
||||||
|
|
||||||
const handleReviewLessonClick = (reviewType: string, lesson: string) => {
|
const handleReviewLessonClick = (reviewType: string, lesson: string) => {
|
||||||
type Question = { question: string, wordBank: string[], expected: string, type: string, exercise: string };
|
type Question = { question: string, wordBank: string[], expected: string, type: string, exercise: string };
|
||||||
|
|||||||
Reference in New Issue
Block a user