Skip to content

Commit

Permalink
Merge pull request #48 from JumboCode/myi/level-page
Browse files Browse the repository at this point in the history
styled levels page, added conversation classes
  • Loading branch information
myix765 authored Nov 17, 2024
2 parents 69388f8 + 592a3e3 commit b1c0419
Show file tree
Hide file tree
Showing 18 changed files with 390 additions and 298 deletions.
44 changes: 34 additions & 10 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const UserSchema = new Schema({

const User = mongoose.model("User", UserSchema)


// Contact Schema
const ContactSchema = new Schema({
name: { type: String, required: true },
Expand All @@ -89,11 +90,14 @@ const ContactSchema = new Schema({

const Contact = mongoose.model('Contact', ContactSchema);

// Class Schema

// Schedule Schema
const ScheduleSchema = new Schema({
day: { type: String, required: true },
time: { type: String, required: true },
})

// Class Schema
const ClassSchema = new Schema({
title: { type: String, required: true },
level: { type: String, required: true },
Expand All @@ -105,6 +109,18 @@ const ClassSchema = new Schema({

const Class = mongoose.model("Class", ClassSchema)


// Conversation Schema
const ConversationSchema = new Schema({
instructor: { type: String, required: true },
ageGroup: { type: String, required: true },
schedule: { type: [ScheduleSchema], required: true, default: [] },
roster: { type: [Schema.Types.ObjectId], default: [] }
}, { collection: 'conversations' })

const Conversation = mongoose.model("Conversation", ConversationSchema)


// Level Schema
const LevelSchema = new Schema({
level: { type: Number, required: true },
Expand Down Expand Up @@ -193,7 +209,7 @@ app.get('/api/users', async (req, res) => {
}
})

// Contact
// Post Contact
app.post('/api/contact', async (req, res) => {
const { name, email, subject, message } = req.body
try {
Expand All @@ -208,34 +224,42 @@ app.post('/api/contact', async (req, res) => {
res.status(201).json({ message: 'Inquiry submitted successfully' })
}
catch (err) {
console.error('Error submitting inquiry:', err);
res.status(500).json({ message: 'Error submitting inquiry' })
res.status(500).json({ message: 'Error submitting inquiry' });
}
})

// Classes
// Get Classes
app.get('/api/classes', async (req, res) => {
try {
const allowedFields = ['level', 'instructor', 'ageGroup'];
const filters = validateInput(req.query, allowedFields);

//apply the filters directly to the database query
const data = await Class.find(filters);
res.json(data)

res.json(data);
} catch (err) {
res.status(500).send(err);
}
})

// Levels
// Get Levels
app.get("/api/levels", async (req, res) => {
try {
const allowedFields = ['level']
const filters = validateInput(req.query, allowedFields)
const allowedFields = ['level'];
const filters = validateInput(req.query, allowedFields);
const data = await Level.find(filters);
res.json(data);
} catch (err) {
res.status(500).send(err);
}
})

// Get Conversation classes
app.get("/api/conversations", async (req, res) => {
try {
const data = await Conversation.find();
res.status(200).json(data);
} catch (error) {
res.status(500).send(err);
}
})
Binary file added public/images/blue_mountains.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 13 additions & 3 deletions src/api/class-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import axios from 'axios'
const apiUrl = (endpoint) => `${import.meta.env.VITE_API_URL}${endpoint}`

// query should be a string
const getClasses = async (query) => {
const getClasses = async (query = "") => {
try {
const response = await axios.get(apiUrl(`/api/classes?${query}`))
return response.data
Expand All @@ -13,7 +13,7 @@ const getClasses = async (query) => {
}

// query should be a string
const getLevels = async (query) => {
const getLevels = async (query = "") => {
try {
const response = await axios.get(apiUrl(`/api/levels?${query}`));
return response.data
Expand All @@ -22,7 +22,17 @@ const getLevels = async (query) => {
}
}

const getConversations = async () => {
try {
const response = await axios.get(apiUrl("/api/conversations/"))
return response.data
} catch (error) {
console.error('Error fetching conversations:', error)
}
}

export {
getClasses,
getLevels
getLevels,
getConversations,
}
4 changes: 2 additions & 2 deletions src/components/Button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ const Button = ({ label, isOutline, onClick }) => {
return (
<button
className={`px-4 py-2 rounded-lg transition-colors duration-300 ${isOutline
? 'border border-cerulean text-black-500 bg-white'
: 'bg-cerulean text-white bg-dark-blue-800'
? 'border border-dark-blue-800 text-black-500 bg-white'
: 'text-white bg-dark-blue-800'
}`}
onClick={onClick}
>
Expand Down
17 changes: 17 additions & 0 deletions src/components/ConversationClass.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

const ConversationClass = ({ conversation }) => {
return (
<div className="w-full h-full rounded-2xl shadow-lg grid grid-rows-[2fr_3fr]">
<div className="bg-[url('/images/blue_mountains.png')] bg-no-repeat bg-cover bg-center rounded-t-2xl"></div>
<div className="bg-white px-6 py-5 row-start-2 rounded-b-2xl">
<h3 className='text-2xl font-semibold'>Talk to {conversation.instructor}</h3>
<p>{conversation.ageGroup.charAt(0).toUpperCase() + conversation.ageGroup.slice(1)} ages</p>
{conversation.schedule.map((schedule, index) => (
<p key={index} className="text-black opacity-50">{schedule.day} {schedule.time}</p>
))}
</div>
</div>
)
}

export default ConversationClass;
2 changes: 1 addition & 1 deletion src/components/Dropdown/Dropdown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const Dropdown = ({ label, children, buttonClassName = "dropdown-button text-rig
type="button"
>
{label}
<IoChevronDownOutline className={`h-4 w-4 text-gray-500 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`} />
<IoChevronDownOutline className={`h-4 w-4 text-black transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`} />
</button>
{/* dropdown */}
{isOpen && (
Expand Down
4 changes: 2 additions & 2 deletions src/components/Dropdown/LanguageDropdown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ const LanguageDropdown = () => {
<Dropdown
label={
<div className="flex items-center space-x-1">
<IoGlobeOutline size={18} className="text-gray-600" />
<IoGlobeOutline size={18} className="text-black" />
<span>{selectedLang}</span>
</div>
}
buttonClassName="flex items-center space-x-1 text-sm font-medium text-gray-600 hover:text-gray-900 min-w-[90px] pl-3 pr-4 py-2 sm:px-3 sm:py-2"
buttonClassName="flex items-center space-x-1 text-base font-normal text-black min-w-fit pl-3 pr-4 py-2 sm:px-3 sm:py-2"
>
{/* drop down links */}
{Object.keys(langMapping).map((lang) => (
Expand Down
36 changes: 15 additions & 21 deletions src/components/Level.jsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
import { Link } from "wouter"

const Level = ({ level, isSimplified }) => {
const params = new URLSearchParams()
params.set("level", level.level)

return (
<Link href={`/classes?${params.toString()}`} className="bg-white px-4 py-3 rounded-lg w-1/4 h-1/4 shadow-md">
{isSimplified ?
// TODO (Fahim & Tony): work on the simplified version of the Level component seen on the Class pages
<div></div>
:
return isSimplified ? (
// TODO (Fahim & Tony): work on the simplified version of the Level component seen on the Class pages
<div></div>
) : (
<div className="w-full h-full rounded-2xl shadow-lg grid grid-rows-[2fr_3fr]">
<div className="bg-[url('/images/blue_mountains.png')] bg-no-repeat bg-cover bg-center rounded-t-2xl"></div>
<div className="bg-white px-6 py-5 row-start-2 rounded-b-2xl">
<h4 className='text-2xl font-semibold'>Level: {level.level}</h4>
<p className="">{level.name}</p>
<div>
<h3 className='text-2xl font-semibold'>Level: {level.level}</h3>
<p>{level.name}</p>
<div>
<p>Instructors:</p>
{level.instructors.map((instructor, instructorIndex) => (
<p key={instructorIndex}>{instructor}</p>
))}
</div>
<p>Instructors:</p>
{level.instructors.map((instructor, instructorIndex) => (
<p key={instructorIndex}>{instructor}</p>
))}
</div>
}

</Link>
</div>
</div>
)
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/NavBar/NavBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const NavBar = () => {
<img className="h-10 w-auto" src={dillarLogo} alt="Dillar English Academy" />
</Link>
{/* Desktop navigation */}
<div className="hidden sm:flex sm:items-center sm:space-x-4">
<div className="hidden sm:flex sm:items-center lg:space-x-20 md:space-x-10">
<NavLink href="/about">About</NavLink>
<NavLink href="/levels">Courses</NavLink>
<NavLink href="/contact">Contact</NavLink>
Expand Down
2 changes: 1 addition & 1 deletion src/components/NavBar/NavLink.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Link } from 'wouter';
const NavLink = ({ href, isMobile, children }) => (
<Link
href={href}
className={`font-medium text-gray-500 text-base ${isMobile ? "block pl-3 pr-4 py-2 border-l-4 border-transparent hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 transition duration-150 ease-in-out" : "hover:bg-gray-100 hover:text-gray-900 px-3 py-2 rounded-md transition duration-150 ease-in-out"}`}
className={`font-normal text-black text-base ${isMobile ? "block pl-3 pr-4 py-2 border-l-4 border-transparent hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 transition duration-150 ease-in-out" : "hover:bg-gray-100 hover:text-gray-900 px-3 py-2 rounded-md transition duration-150 ease-in-out"}`}
>
{children}
</Link>
Expand Down
5 changes: 5 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
@tailwind components;
@tailwind utilities;

@font-face {
font-family: 'Avenir';
src: url('./assets/fonts/AvenirLTStd-Book.otf') format('opentype');
}

@font-face {
font-family: 'Avenir';
src: url('./assets/fonts/AvenirLTStd-Roman.otf') format('opentype');
Expand Down
45 changes: 21 additions & 24 deletions src/pages/About.jsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
import founder from '../assets/founder.jpg'
import founder from '../assets/founder.jpg';
import { useTranslation } from "react-i18next";

function About() {
const { t } = useTranslation();
return (
<>
<div className="flex flex-col sm:flex-row-reverse sm:justify-between h-full sm:px-16 px-4">
<div className="flex items-center justify-center sm:w-1/3">
<img src={founder} alt="dummy-founder-image" title="dummy-image"></img>
</div>
<div className="my-auto sm:w-7/12 sm:text-lg">
<h1 className="text-4xl py-5 sm:text-5xl text-center sm:text-left">{t("about_heading")}</h1>
<p>Dillar English Academy was founded by Dilnawa and Dilziba Dilmurat
Kizghin to help Uyghurs around the world learn English without cost.
With the help and commitment of our volunteer teachers, our goal is
to bridge the educational disparity gap among Uyghurs worldwide.
<br /><br />
Dillar Academy has grown exponentially in a short time! Recognizing a
need in the international Uyghur community, we have recruited Uyghur
college students in America to volunteer their time and teach various
levels of English. Although our teachers are not certified English
language instructors, they are native English speakers who invest
time into teaching the best information that they can.
</p>
</div>
<div className="flex flex-col sm:flex-row-reverse sm:justify-between h-full xl:px-16 md:px-6 px-4">
<div className="flex items-center justify-center sm:w-1/3">
<img src={founder} alt="dummy-founder-image" title="dummy-image"></img>
</div>

</>
<div className="my-auto sm:w-7/12 sm:text-lg">
<h1 className="text-4xl py-5 sm:text-5xl text-center sm:text-left">{t("about_heading")}</h1>
<p>Dillar English Academy was founded by Dilnawa and Dilziba Dilmurat
Kizghin to help Uyghurs around the world learn English without cost.
With the help and commitment of our volunteer teachers, our goal is
to bridge the educational disparity gap among Uyghurs worldwide.
<br /><br />
Dillar Academy has grown exponentially in a short time! Recognizing a
need in the international Uyghur community, we have recruited Uyghur
college students in America to volunteer their time and teach various
levels of English. Although our teachers are not certified English
language instructors, they are native English speakers who invest
time into teaching the best information that they can.
</p>
</div>
</div>
)
}

export default About
export default About;
2 changes: 1 addition & 1 deletion src/pages/Classes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const Classes = () => {
return (
<div className='px-8 py-6'>
<h3>Level {level.level}</h3>
<h1 className='text-4xl font-bold'>{level.name}</h1>
<h1 className='text-4xl font-extrabold'>{level.name}</h1>
<div className='flex gap-3 mt-4'>
{classes.map((classObj, classIndex) => (
<Class key={classIndex} classObj={classObj} />
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Home.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const Home = () => {
<>
<div className="bg-sky-200 p-4 min-h-[60dvh] flex items-center">
<div className="text-center md:text-left mb-12 mt-12 px-5">
<h1 className="text-4xl font-bold mb-2">Dillar Academy</h1>
<h1 className="text-4xl font-extrabold mb-2">Dillar Academy</h1>
<p className="text-lg mb-4">Free English education for Uyghurs around the world.</p>
<div className="flex flex-col md:flex-row items-center">
<Button
Expand All @@ -45,7 +45,7 @@ const Home = () => {
</div>
</div>
<div className="bg-white p-4 mt-4">
<h1 className="text-4xl font-bold mb-10 text-center">How It Works</h1>
<h1 className="text-4xl font-extrabold mb-10 text-center">How It Works</h1>
{sections.map((section, index) => (
<div key={index} className={`flex flex-col md:flex-row items-center justify-evenly px-4 md:px-2 mb-4 ${index % 2 === 1 ? 'md:flex-row-reverse' : ''}`}>
<img src={section.imgSrc} alt={section.imgAlt} className="mb-4 md:mb-8 md:w-1/3 rounded-lg shadow-md" />
Expand Down
Loading

0 comments on commit b1c0419

Please sign in to comment.