Compare commits

..

3 commits

Author SHA1 Message Date
Alex Stan 6c8be718a2 Fixed merge conflict
Signed-off-by: Alex Stan <90788596+Ultra980@users.noreply.github.com>
2024-06-01 15:46:54 +03:00
Alex Stan 22f59ca619 Added a TopicCard component
Signed-off-by: Alex Stan <90788596+Ultra980@users.noreply.github.com>
2024-06-01 15:44:25 +03:00
Alex Stan 882dd995f9 Added the question and session api and a form component
Signed-off-by: Alex Stan <90788596+Ultra980@users.noreply.github.com>
2024-06-01 15:13:30 +03:00
30 changed files with 205 additions and 1607 deletions

View file

@ -1,7 +1,3 @@
{
"extends": "next/core-web-vitals",
"rules": {
"react/no-unescaped-entities": "off",
"react/jsx-key": "off"
}
"extends": "next/core-web-vitals"
}

1
.gitignore vendored
View file

@ -34,4 +34,3 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
app/test/*

View file

@ -1,10 +1,36 @@
# ***FlashLearn***
> The React based app with flashcards for you to learn. Made for the INFOMATRIX 2024 Hackathon.
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
**How to use:**
1. **Click the "Get Started" Button.**
2. **Select a subject.**
3. ***Learn!***
## Getting Started
*Made with the MIT Licence*
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.

View file

@ -1,705 +1,75 @@
{
"questions": [
{
"id": 1,
"category": "cpp",
"type": "none",
"text": "What is the output of the expression 3 + 2 * 5 in C++?",
"answer": "13"
},
{
"id": 2,
"category": "cpp",
"type": "none",
"text": "What is the default access specifier for class members in C++?",
"answer": "private"
},
{
"id": 3,
"category": "cpp",
"type": "none",
"text": "What is the name of the process that automatically converts a primitive type to its corresponding wrapper class object in C++?",
"answer": "Boxing"
},
{
"id": 4,
"category": "cpp",
"type": "none",
"text": "Which C++ feature allows the creation of a function or an operator with more than one form?",
"answer": "Polymorphism"
},
{
"id": 5,
"category": "cpp",
"type": "none",
"text": "What is the main purpose of a constructor in C++?",
"answer": "To initialize an object"
},
{
"id": 6,
"category": "cpp",
"type": "none",
"text": "What does STL stand for in C++?",
"answer": "Standard Template Library"
},
{
"id": 7,
"category": "cpp",
"type": "none",
"text": "Which operator is used to access the members of a structure through a pointer in C++?",
"answer": "->"
},
{
"id": 8,
"category": "cpp",
"type": "none",
"text": "What is the keyword used to define a constant in C++?",
"answer": "const"
},
{
"id": 9,
"category": "cpp",
"type": "none",
"text": "What is the primary purpose of the 'new' operator in C++?",
"answer": "To allocate memory dynamically"
},
{
"id": 10,
"category": "cpp",
"type": "none",
"text": "What does RTTI stand for in C++?",
"answer": "Run-Time Type Information"
},
{
"id": 11,
"category": "cpp",
"type": "none",
"text": "What is a pure virtual function in C++?",
"answer": "A function with no definition that must be overridden in derived classes"
},
{
"id": 12,
"category": "cpp",
"type": "none",
"text": "What is the name of the feature that allows the same function name to be used for different types in C++?",
"answer": "Function Overloading"
},
{
"id": 13,
"category": "cpp",
"type": "none",
"text": "What is a 'namespace' in C++?",
"answer": "A declarative region that provides a scope to the identifiers inside it"
},
{
"id": 14,
"category": "cpp",
"type": "none",
"text": "Which C++ keyword is used to prevent a variable from being modified?",
"answer": "const"
},
{
"id": 15,
"category": "cpp",
"type": "none",
"text": "What is the function of the 'friend' keyword in C++?",
"answer": "To allow a function or another class access to the private and protected members of a class"
},
{
"id": 16,
"category": "cpp",
"type": "none",
"text": "What is 'inheritance' in C++?",
"answer": "The process by which one class acquires the properties and functionalities of another class"
},
{
"id": 17,
"category": "cpp",
"type": "none",
"text": "Which operator is used for scope resolution in C++?",
"answer": "::"
},
{
"id": 18,
"category": "cpp",
"type": "none",
"text": "What is a 'destructor' in C++?",
"answer": "A special member function that is executed when an object of its class is destroyed"
},
{
"id": 19,
"category": "cpp",
"type": "none",
"text": "What is the primary use of the 'this' pointer in C++?",
"answer": "To refer to the calling object itself"
},
{
"id": 20,
"category": "cpp",
"type": "none",
"text": "What is the return type of the main function in C++?",
"answer": "int"
},
{
"id": 21,
"category": "cybersec",
"type": "none",
"text": "What does 'phishing' mean in cybersecurity?",
"answer": "A technique used to trick users into providing sensitive information by pretending to be a trustworthy entity"
},
{
"id": 22,
"category": "cybersec",
"type": "none",
"text": "What is the purpose of a firewall in network security?",
"answer": "To monitor and control incoming and outgoing network traffic based on predetermined security rules"
},
{
"id": 23,
"category": "cybersec",
"type": "none",
"text": "What does 'DDoS' stand for?",
{
"id": "1",
"category": "C++",
"type": "quiz",
"question": "What is the output of the following code: std::cout << sizeof(int);",
"answer": "The output depends on the system, typically 4 on most systems."
},
{
"id": "2",
"category": "geography",
"type": "quiz",
"question": "What is the capital of France?",
"answer": "Paris"
},
{
"id": "3",
"category": "cybersecurity",
"type": "true or false",
"question": "A firewall can protect a network from all types of cyber attacks.",
"answer": "false"
},
{
"id": "4",
"category": "C++",
"type": "true or false",
"question": "C++ supports multiple inheritance.",
"answer": "true"
},
{
"id": "5",
"category": "geography",
"type": "quiz",
"question": "Which is the largest continent by land area?",
"answer": "Asia"
},
{
"id": "6",
"category": "cybersecurity",
"type": "quiz",
"question": "What does the acronym 'DDoS' stand for?",
"answer": "Distributed Denial of Service"
},
{
"id": 24,
"category": "cybersec",
"type": "none",
"text": "What is a 'zero-day' exploit?",
"answer": "A cyber attack that occurs on the same day a vulnerability is discovered and before a fix is implemented"
},
{
"id": 25,
"category": "cybersec",
"type": "none",
"text": "What is 'encryption' in the context of cybersecurity?",
"answer": "The process of converting information or data into a code to prevent unauthorized access"
},
{
"id": 26,
"category": "cybersec",
"type": "none",
"text": "What does 'VPN' stand for in cybersecurity?",
"answer": "Virtual Private Network"
},
{
"id": 27,
"category": "cybersec",
"type": "none",
"text": "What is a 'trojan horse' in cybersecurity?",
"answer": "A type of malware that disguises itself as legitimate software"
},
{
"id": 28,
"category": "cybersec",
"type": "none",
"text": "What is the primary goal of social engineering attacks?",
"answer": "To manipulate individuals into divulging confidential information"
},
{
"id": 29,
"category": "cybersec",
"type": "none",
"text": "What is 'ransomware'?",
"answer": "A type of malware that encrypts a user's data and demands payment to restore access"
},
{
"id": 30,
"category": "cybersec",
"type": "none",
"text": "What does 'SQL injection' exploit?",
"answer": "Vulnerabilities in an application's software by inserting malicious SQL code"
},
{
"id": 31,
"category": "cybersec",
"type": "none",
"text": "What is 'two-factor authentication'?",
"answer": "A security process that requires two different forms of identification to access an account"
},
{
"id": 32,
"category": "cybersec",
"type": "none",
"text": "What is 'malware'?",
"answer": "Software designed to disrupt, damage, or gain unauthorized access to computer systems"
},
{
"id": 33,
"category": "cybersec",
"type": "none",
"text": "What does 'TLS' stand for in cybersecurity?",
"answer": "Transport Layer Security"
},
{
"id": 34,
"category": "cybersec",
"type": "none",
"text": "What is 'brute force attack' in cybersecurity?",
"answer": "A method to find passwords or encryption keys by trying every possible combination"
},
{
"id": 35,
"category": "cybersec",
"type": "none",
"text": "What is the primary function of an Intrusion Detection System (IDS)?",
"answer": "To monitor network traffic for suspicious activity and potential threats"
},
{
"id": 36,
"category": "cybersec",
"type": "none",
"text": "What is 'spoofing' in cybersecurity?",
"answer": "The act of disguising a communication from an unknown source as being from a known, trusted source"
},
{
"id": 37,
"category": "cybersec",
"type": "none",
"text": "What is 'rootkit'?",
"answer": "A type of malicious software designed to hide the existence of certain processes or programs from normal methods of detection"
},
{
"id": 38,
"category": "cybersec",
"type": "none",
"text": "What does 'CVE' stand for in cybersecurity?",
"answer": "Common Vulnerabilities and Exposures"
},
{
"id": 39,
"category": "cybersec",
"type": "none",
"text": "What is 'pharming' in cybersecurity?",
"answer": "A cyber attack intended to redirect a website's traffic to another, fake site"
},
{
"id": 40,
"category": "cybersec",
"type": "none",
"text": "What does 'APT' stand for in cybersecurity?",
"answer": "Advanced Persistent Threat"
},
{
"id": 41,
"category": "cybersec",
"type": "none",
"text": "What is 'cross-site scripting' (XSS)?",
"answer": "A vulnerability that allows attackers to inject malicious scripts into webpages viewed by users"
},
{
"id": 42,
"category": "cybersec",
"type": "none",
"text": "What does 'BYOD' stand for in cybersecurity?",
"answer": "Bring Your Own Device"
},
{
"id": 43,
"category": "cybersec",
"type": "none",
"text": "What is 'penetration testing'?",
"answer": "A method of evaluating the security of a computer system by simulating an attack"
},
{
"id": 44,
"category": "cybersec",
"type": "none",
"text": "What does 'CIA' stand for in cybersecurity?",
"answer": "Confidentiality, Integrity, and Availability"
},
{
"id": 45,
"category": "cybersec",
"type": "none",
"text": "What is 'smishing'?",
"answer": "A type of phishing attack that uses SMS messages to lure victims"
},
{
"id": 46,
"category": "cybersec",
"type": "none",
"text": "What is a 'honeypot' in cybersecurity?",
"answer": "A security system set up to attract and detect hackers"
},
{
"id": 47,
"category": "cybersec",
"type": "none",
"text": "What is the purpose of 'endpoint protection'?",
"answer": "To secure endpoints or entry points of end-user devices such as desktops, laptops, and mobile devices"
},
{
"id": 48,
"category": "cybersec",
"type": "none",
"text": "What does 'SIEM' stand for in cybersecurity?",
"answer": "Security Information and Event Management"
},
{
"id": 49,
"category": "cybersec",
"type": "none",
"text": "What is a 'man-in-the-middle' attack?",
"answer": "A cyber attack where the attacker secretly intercepts and relays messages between two parties"
},
{
"id": 50,
"category": "cybersec",
"type": "none",
"text": "What is 'data exfiltration'?",
"answer": "The unauthorized transfer of data from a computer"
},
{
"id": 51,
},
{
"id": "7",
"category": "C++",
"type": "quiz",
"question": "Which C++ standard introduced the concept of 'auto' keyword?",
"answer": "C++11"
},
{
"id": "8",
"category": "geography",
"type": "none",
"text": "What is the longest river in the world?",
"answer": "The Nile River"
},
{
"id": 52,
"category": "geography",
"type": "none",
"text": "What is the capital city of Australia?",
"answer": "Canberra"
},
{
"id": 53,
"category": "geography",
"type": "none",
"text": "Which desert is the largest in the world?",
"answer": "The Sahara Desert"
},
{
"id": 54,
"category": "geography",
"type": "none",
"text": "What is the smallest country in the world by land area?",
"answer": "Vatican City"
},
{
"id": 55,
"category": "geography",
"type": "none",
"text": "What mountain range forms the natural border between France and Spain?",
"answer": "The Pyrenees"
},
{
"id": 56,
"category": "geography",
"type": "none",
"text": "Which country has the most natural lakes?",
"answer": "Canada"
},
{
"id": 57,
"category": "geography",
"type": "none",
"text": "What is the highest mountain in Africa?",
"answer": "Mount Kilimanjaro"
},
{
"id": 58,
"category": "geography",
"type": "none",
"text": "What is the capital of Japan?",
"answer": "Tokyo"
},
{
"id": 59,
"category": "geography",
"type": "none",
"text": "What river runs through the Grand Canyon?",
"answer": "The Colorado River"
},
{
"id": 60,
"category": "geography",
"type": "none",
"text": "Which country is known as the Land of the Rising Sun?",
"answer": "Japan"
},
{
"id": 61,
"category": "geography",
"type": "none",
"text": "What is the largest island in the world?",
"answer": "Greenland"
},
{
"id": 62,
"category": "geography",
"type": "none",
"text": "Which European country shares borders with the most neighbors?",
"answer": "Germany"
},
{
"id": 63,
"category": "geography",
"type": "none",
"text": "What is the deepest ocean trench in the world?",
"answer": "The Mariana Trench"
},
{
"id": 64,
"category": "geography",
"type": "none",
"text": "Which U.S. state is the largest by area?",
"answer": "Alaska"
},
{
"id": 65,
"category": "geography",
"type": "none",
"text": "What is the capital city of Canada?",
"answer": "Ottawa"
},
{
"id": 66,
"category": "geography",
"type": "none",
"text": "Which river is the longest in Europe?",
"answer": "The Volga River"
},
{
"id": 67,
"category": "geography",
"type": "none",
"text": "Which continent has the most countries?",
"answer": "Africa"
},
{
"id": 68,
"category": "geography",
"type": "none",
"text": "What is the capital of Brazil?",
"answer": "Brasília"
},
{
"id": 69,
"category": "geography",
"type": "none",
"text": "What is the official language of Egypt?",
"answer": "Arabic"
},
{
"id": 70,
"category": "geography",
"type": "none",
"text": "Which ocean is the largest by surface area?",
"answer": "The Pacific Ocean"
},
{
"id": 71,
"category": "geography",
"type": "none",
"text": "What is the name of the sea bordered by Europe to the north and Africa to the south?",
"answer": "The Mediterranean Sea"
},
{
"id": 72,
"category": "geography",
"type": "none",
"text": "Which country has the most islands?",
"answer": "Sweden"
},
{
"id": 73,
"category": "geography",
"type": "none",
"text": "What is the largest country in South America?",
"answer": "Brazil"
},
{
"id": 74,
"category": "geography",
"type": "none",
"text": "What is the longest mountain range in the world?",
"answer": "The Andes"
},
{
"id": 75,
"category": "geography",
"type": "none",
"text": "What is the capital city of Russia?",
"answer": "Moscow"
},
{
"id": 76,
"category": "geography",
"type": "none",
"text": "What is the largest desert in Asia?",
"answer": "The Gobi Desert"
},
{
"id": 77,
"category": "geography",
"type": "none",
"text": "What is the capital of Kenya?",
"answer": "Nairobi"
},
{
"id": 78,
"category": "geography",
"type": "none",
"text": "Which country is the smallest in Europe by land area?",
"answer": "Vatican City"
},
{
"id": 79,
"category": "geography",
"type": "none",
"text": "Which river forms part of the border between Mexico and the United States?",
"answer": "The Rio Grande"
},
{
"id": 80,
"category": "geography",
"type": "none",
"text": "What is the capital city of South Korea?",
"answer": "Seoul"
},
{
"id": 81,
"category": "geography",
"type": "none",
"text": "What is the largest country in Africa by land area?",
"answer": "Algeria"
},
{
"id": 82,
"category": "geography",
"type": "none",
"text": "Which country is known as the Land of the Maple Leaf?",
"answer": "Canada"
},
{
"id": 83,
"category": "geography",
"type": "none",
"text": "Which river is the longest in Asia?",
"answer": "The Yangtze River"
},
{
"id": 84,
"category": "geography",
"type": "none",
"text": "What is the capital city of India?",
"answer": "New Delhi"
},
{
"id": 85,
"category": "geography",
"type": "none",
"text": "Which ocean lies on the east coast of the United States?",
"answer": "The Atlantic Ocean"
},
{
"id": 86,
"category": "geography",
"type": "none",
"text": "What is the capital city of Italy?",
"answer": "Rome"
},
{
"id": 87,
"category": "geography",
"type": "none",
"text": "Which river is the main river that flows through Paris?",
"answer": "The Seine"
},
{
"id": 88,
"category": "geography",
"type": "none",
"text": "What is the smallest ocean in the world?",
"answer": "The Arctic Ocean"
},
{
"id": 89,
"category": "geography",
"type": "none",
"text": "What is the capital city of Mexico?",
"answer": "Mexico City"
},
{
"id": 90,
"category": "geography",
"type": "none",
"text": "Which country is known for its unique wildlife and has the Great Barrier Reef?",
"answer": "Australia"
},
{
"id": 91,
"category": "geography",
"type": "none",
"text": "What is the capital of Argentina?",
"answer": "Buenos Aires"
},
{
"id": 92,
"category": "geography",
"type": "none",
"text": "Which country has the largest population in the world?",
"answer": "China"
},
{
"id": 93,
"category": "geography",
"type": "none",
"text": "What is the capital city of the United Kingdom?",
"answer": "London"
},
{
"id": 94,
"category": "geography",
"type": "none",
"text": "Which continent is known as the birthplace of humanity?",
"answer": "Africa"
},
{
"id": 95,
"category": "geography",
"type": "none",
"text": "What is the capital city of Thailand?",
"answer": "Bangkok"
},
{
"id": 96,
"category": "geography",
"type": "none",
"text": "What is the capital of Egypt?",
"answer": "Cairo"
},
{
"id": 97,
"category": "geography",
"type": "none",
"text": "Which country is home to the Amazon Rainforest?",
"answer": "Brazil"
},
{
"id": 98,
"category": "geography",
"type": "none",
"text": "What is the capital city of Spain?",
"answer": "Madrid"
},
{
"id": 99,
"category": "geography",
"type": "none",
"text": "What is the currency of Japan?",
"answer": "Yen"
},
{
"id": 100,
"category": "geography",
"type": "none",
"text": "Which country is known as the Land of Fire and Ice?",
"answer": "Iceland"
}
],
"sessions": []
}
"type": "true or false",
"question": "The Amazon River is the longest river in the world.",
"answer": "false"
},
{
"id": "9",
"category": "cybersecurity",
"type": "quiz",
"question": "What is the main purpose of encryption?",
"answer": "To protect data confidentiality by converting it into a code."
},
{
"id": "10",
"category": "C++",
"type": "quiz",
"question": "What is the function of the 'virtual' keyword in C++?",
"answer": "It allows a member function to be overridden in a derived class."
}
]
}

View file

@ -1,110 +0,0 @@
import { ClipboardDocumentListIcon, DocumentTextIcon } from '@heroicons/react/24/outline';
import Logo from '../components/logo';
import TopicCard from '../components/topic_card';
import LinkButton from '../components/link-button';
{/*Index of people and their respective image and title*/}
const people = [
{
name: 'Andrei Banu',
role: 'UI/UX designer',
imageUrl:
'arch.png',
email: 'mailto:child1.andy@gmail.com'
},
{
name: 'Ioan Cristian Chelaru',
role: 'UI/UX designer',
imageUrl:
'blahaj.avif',
email: 'mailto:iccjoc@proton.me'
},
{
name: 'Alexandru Gabriel Stan',
role: 'Backend & UI developer',
imageUrl:
'alex.png',
email: 'mailto:alex.stan.2010@proton.me'
},
// More people...
]
export default function Example() {
return (
<div className="sm:py-32">
{/*Background visuals*/}
<div
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true"
>
<div
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
<div
className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
</div>
<Logo/>
<div style={{paddingBottom: '100px'}}></div>
<div className="mx-auto grid max-w-7xl gap-x-8 gap-y-20 px-6 lg:px-8 xl:grid-cols-3"> {/*Team presentation text*/}
<div className="max-w-2xl">
<h2 className="text-3xl font-bold tracking-tight text-gray-200 sm:text-4xl">Meet our developers</h2>
<p className="mt-6 text-lg leading-8 text-gray-200">
We are a group of passionate middle schoolers that got together to hopefully make a difference in the world
</p>
</div>
{/*Display people*/}
<ul role="list" className="grid gap-x-8 gap-y-12 sm:grid-cols-2 sm:gap-y-16 xl:col-span-2">
{people.map((person) => (
<li key={person.name}>
<div className="flex items-center gap-x-6">
<img className="h-16 w-16 rounded-full" src={person.imageUrl} alt="" />
<div>
<h3 className="text-base font-semibold leading-7 tracking-tight text-gray-200">{person.name}</h3>
<p className="text-sm font-semibold leading-6 text-indigo-200">{person.role}</p>
<LinkButton text="Send mail" href={person.email}/>
</div>
</div>
</li>
))}
</ul>
</div>
<br></br>
{/*Licence and source code buttons*/}
<div
style={{display:"flex", alignItems: 'center', alignSelf:'center', justifyContent: 'center', marginLeft: "40px", marginRight: "40px"}}
>
<a
href="https://git.gra.phite.ro/BlahajTeam/next-app"
className="rounded-md text-sm font-semibold text-gray-200 shadow-sm hover:text-gray-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
style={{minWidth: '190px', maxWidth: '190px', paddingLeft: '50px', paddingRight: '50px', paddingTop: '20px', paddingBottom: '20px', alignSelf: 'center'}}
>
<DocumentTextIcon></DocumentTextIcon>
Source Code
</a>
<a
href="https://git.gra.phite.ro/BlahajTeam/next-app/src/branch/main/LICENSE"
className="rounded-md text-sm font-semibold text-gray-200 shadow-sm hover:text-gray-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
style={{minWidth: '190px', maxWidth: '190px', paddingLeft: '50px', paddingRight: '50px', paddingTop: '20px', paddingBottom: '20px', alignSelf: 'center'}}
>
<ClipboardDocumentListIcon></ClipboardDocumentListIcon>
Our Licence
</a>
</div>
<div
className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
aria-hidden="true"
>
</div>
</div>
)
}

View file

@ -1,49 +1,43 @@
'use client';
import { useState } from "react";
export enum FieldType {
number = 'number',
text = 'text'
}
export type FormFields = {
type: FieldType,
name: string,
label: string,
required: boolean
}
const Form = <T,>({ fields, onSubmit }) => {
const [formData, setFormData] = useState({});
const handleChange = (event) => {
const { name, value } = event.target;
setFormData( (prevData) => ({
...prevData,
[name]: value
}));
}
const Form = <T,>({ initialData, onSubmit }) => {
const [formData, setFormData] = useState( initialData );
const handleSubmit = (event) => {
event.preventDefault();
//q = formData;
//addQuestion( q );
//console.log( `Adding question ${JSON.stringify(q)}` );
onSubmit( formData );
}
const handleChange = (event) => {
const { name, value } = event.target;
setFormData( (prevData) => ({
...prevData,
[name]: value
}));
}
return (
<form onSubmit={handleSubmit}>
{fields.map( (field) => {
return (
<div key={field.name}>
<label>{field.label}</label>
<input
type={field.type}
name={field.name}
value={formData[field.name] || ''}
onChange={handleChange}
required={field.required}
/>
</div>
)})}
<form onSubmit={handleSubmit} className="flex">
<div>
{Object.entries( initialData ).map( (key, val) => {
return(
<input
type = { typeof( val ) == typeof( 0 ) ? "number" : "text" /* pretty hacky, we should change this */ }
id = {key[0]}
name = {key[0]}
value = {formData[key[0]]}
onChange = {handleChange}
required
/>)})}
</div>
<button type="submit">Submit</button>
</form>
);

View file

@ -1,26 +0,0 @@
'use client';
import { motion } from "framer-motion"
import { useState } from "react";
const LinkButton = ({text, href, onPress}: {text: string, href: string, onPress?: () => any}) => {
const [buttonHovered, setButtonHovered] = useState( false );
const [buttonPressed, setButtonPressed] = useState( false );
return (
<div className="mt-10 flex items-center justify-center gap-x-6 lg:justify-start">
<motion.a
href={href}
className="rounded-md bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
style={{ marginBottom: '40px' }}
animate={{opacity: buttonHovered ? 0.8 : 1}}
onMouseEnter={()=>setButtonHovered(true)}
onMouseLeave={()=>setButtonHovered(false)}
onClick={()=>{setButtonPressed(true); onPress && onPress();}}
>
{text}
</motion.a>
</div>
);
}
export default LinkButton;

View file

@ -1,45 +0,0 @@
'use client';
import { Transition } from "@headlessui/react";
import { motion } from "framer-motion";
import { useState } from "react";
import LinkButton from "./link-button";
const Logo = () => {
const [logoHovered, setLogoHovered] = useState( false );
const [aboutButtonHovered, setAboutButtonHovered] = useState( false );
return (
<div style={{ display:"flex", alignItems: 'center', justifyContent: 'center', marginLeft: "40px", marginRight: "40px"}}>
{/* <Transition
appear={false}
show={true}
enter="transition-opacity duration-75"
enterFrom={logoHovered ? "opacity-100" : "opacity-70"}
enterTo={logoHovered ? "opacity-70" : "opacity-100"}
leave="transition-opacity duration-75"
leaveFrom={logoHovered ? "opacity-70" : "opacity-100"}
leaveTo={logoHovered ? "opacity-100" : "opacity-70"}> */}
<motion.a href="/" style={{ marginBottom: '40px', marginLeft: '40px'}} animate={{opacity: logoHovered ? 0.7 : 1}}
onMouseEnter={()=>setLogoHovered(true)}
onMouseLeave={()=>setLogoHovered(false)}>
<img src="/logo-no-background.png" height="auto" width="400px"/>
</motion.a>
{/* </Transition> */}
<div style={{ marginBottom: '40px', marginRight: '50px' }}></div>
{/* <motion.a
href="/about-us"
className="rounded-md bg-white text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
style={{ marginBottom: '40px', marginRight: '40px', padding: '10px' }}
animate={{opacity: aboutButtonHovered ? 0.8 : 1}}
onMouseEnter={()=>setAboutButtonHovered(true)}
onMouseLeave={()=>setAboutButtonHovered(false)}
>
About us
</motion.a> */}
<LinkButton text="About us" href="/about-us"/>
</div>
)
}
export default Logo;

View file

@ -1,120 +0,0 @@
import { ReactComponentElement, ReactNode, useEffect } from "react";
import { AnswerType, Question } from "../lib/question";
import { SessionState } from "../lib/session";
import { CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/outline";
import { Button, Transition } from "@headlessui/react";
import wait from "../lib/delay";
import { motion } from "framer-motion";
const QuestionView = ({ question, setState, state }: { question: Question, setState: any, state: SessionState }) => {
const handleOpenClick = () => {
setState( (prevState: SessionState) => ({
...prevState,
opened: {
...prevState.opened,
[question.id]: !prevState.opened[ question.id ]
}
}))
}
useEffect( () => {
wait( 1000 );
}, [] );
const handleAnswerClick = (right: boolean) => {
setState( (prevState: SessionState) => ({
...prevState,
answered: prevState.answered + 1,
wrong: prevState.wrong + (right ? 0 : 1),
right: prevState.right + (right ? 1 : 0),
answer: {
...prevState.answer,
[question.id]: right ? AnswerType.Right : AnswerType.Wrong
}
}))
question.answered = right ? AnswerType.Right : AnswerType.Wrong;
}
return (
<div className="mx-auto max-w-2xl py-32 sm:py-48 lg:py-56">
<div className="text-center">
{/* {question && question.text} */}
<Transition
appear={true}
show={question ? true : false /* a bit hacky */}
enter="transition-opacity duration-300"
enterFrom="opacity-0"
enterTo="opacity-90"
leave="transition-opacity duration-150"
leaveFrom="opacity-90"
leaveTo="opacity-0">
<h1 className="text-4xl font-bold tracking-tight text-gray-50">
{question.text}
</h1>
</Transition>
{/* <Transition
show={(question && state.opened[ question.id ]) ? true : false}
enter="transition-opacity duration-300"
enterFrom="opacity-0"
enterTo="opacity-90"
leave="transition-opacity duration-150"
leaveFrom="opacity-90"
leaveTo="opacity-0"> */}
{/* <motion.div animate={{visibility: ((question && state.opened[ question.id ]) ? "visible" : "collapse") }}> */}
<motion.div animate={(question && state.opened[ question.id ]) ? {visibility: "visible", opacity: 1} : {visibility: "collapse", opacity: 0}}>
<div><p className="mt-6 text-lg leading-8 text-gray-200">
{question.answer}
</p>
{/* <div className="mt-10 flex items-center justify-center gap-x-6">
<button
onClick={() => { handleAnswerClick( true )}}
className="rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
I knew that!
</button>
<button
onClick={() => {handleAnswerClick( false )}}
className="text-sm font-semibold leading-6 text-gray-300"
>
I didn't know that!
</button>
</div> */}
<div className="mt-10 flex items-center justify-center gap-x-6">
<button
onClick={() => { handleAnswerClick( true )}}
className="rounded-md bg-green-600 px-3.5 py-2.5 text-s font-semibold text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
style={{minWidth:'40%', minHeight:'40%', maxWidth:'40%', maxHeight:'40%'}}
>
<CheckCircleIcon></CheckCircleIcon>
I knew that!
</button>
<button
onClick={() => {handleAnswerClick( false )}}
className="rounded-md bg-red-600 px-3.5 py-2.5 text-s font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
style={{minWidth:'40%', minHeight:'40%', maxWidth:'40%', maxHeight:'40%'}}
>
<XCircleIcon></XCircleIcon>
I didn't know!
</button>
</div>
</div>
</motion.div>
<Transition
show={(question && (state.opened[ question.id ])) ? false : true}
enter="transition-opacity duration-300"
enterFrom="opacity-0"
enterTo="opacity-90"
leave="transition-opacity duration-150"
leaveFrom="opacity-90"
leaveTo="opacity-0">
<Button className="leading-6 text-black back rounded-md bg-white text-sm font-semibold text-gray-900" onClick={handleOpenClick} style = {{padding: '5px'}}>
Show answer
</Button>
</Transition>
</div>
</div>
)
}
export default QuestionView;

View file

@ -1,113 +0,0 @@
import { CheckIcon, XMarkIcon, QuestionMarkCircleIcon, FingerPrintIcon, LockClosedIcon } from '@heroicons/react/24/outline'
import Logo from './logo';
import { SessionState } from '../lib/session';
import LinkButton from './link-button';
/*
const features = [
{
name: 'Correct Questions',
description:
'You got [insert number here] questions right! Good Job!',
icon: CheckIcon,
},
{
name: 'Incorrect Questions',
description:
'You got [insert number here] questions wrong! You can do better!',
icon: XMarkIcon,
},
{
name: 'Total Questions',
description:
'There were [insert number here] questions in total.',
icon: QuestionMarkCircleIcon,
}
]
*/
const Result = ({name, text1, number, text2, Icon}: {name: string, text1: string, number: number, text2: string, Icon: any}) => {
return (
<div className="relative pl-16">
<dt className="text-base font-semibold leading-7 text-gray-100">
<div className="absolute left-0 top-0 flex h-10 w-10 items-center justify-center rounded-lg bg-indigo-600">
<Icon className="h-6 w-6 text-white" aria-hidden="true"/>
</div>
{name}
</dt>
<dd className="mt-2 text-base leading-7 text-gray-300">{`${text1} ${number} ${text2}`}</dd>
</div>
// {/* <p className="relative pl-16">{`${text1} ${number} ${text2}`}</p> */}
)
}
const ResultScreen = ({state}: {state: SessionState}) => {
return (
<div className="py-24 sm:py-32">
<div
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true"
>
<div
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
</div>
<div style={{paddingBottom: '128px'}}></div>
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<div className="mx-auto max-w-2xl lg:text-center">
<h2 className="text-base font-semibold leading-7 text-indigo-300">You did it!</h2>
<p className="mt-2 text-3xl font-bold tracking-tight text-gray-100 sm:text-4xl">
Here are the results:
</p>
<p className="mt-6 text-lg leading-8 text-gray-600">
On this page you can see what you did at the quiz. We'll give your wrong questions again, another time!
</p>
</div>
<div className="mx-auto mt-16 max-w-2xl sm:mt-20 lg:mt-24 lg:max-w-4xl">
<dl className="grid max-w-xl grid-cols-1 gap-x-8 gap-y-10 lg:max-w-none lg:grid-cols-2 lg:gap-y-16">
{/* {features.map((feature) => (
<div key={feature.name} className="relative pl-16">
<dt className="text-base font-semibold leading-7 text-gray-100">
<div className="absolute left-0 top-0 flex h-10 w-10 items-center justify-center rounded-lg bg-indigo-600">
<feature.icon className="h-6 w-6 text-white" aria-hidden="true" />
</div>
{feature.name}
</dt>
<dd className="mt-2 text-base leading-7 text-gray-300">{feature.description}</dd>
</div>
))} */}
<Result name="Correct Answers" key="correct" text1="Congrats for your" number={state.right} text2="correctly answered questions! Great job!" Icon={CheckIcon}/>
<Result name="Wrong Answers" key="wrong" text1="You had" number={state.wrong} text2="wrong answers... It's never too late to learn!" Icon={XMarkIcon}/>
<Result name="Total Answers" key="total" text1="The" number={state.answered} text2="questions you answered surely helped you learn more." Icon={QuestionMarkCircleIcon}/>
</dl>
<br></br>
{/* <a
href="/sessionconfig"
className="rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-gray-100 shadow-sm hover:bg-indigo-900 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
style={{ marginTop: '100px' }}
>
Go Back
</a> */}
<LinkButton text="Learn about another topic" href="/sessionconfig"/>
</div>
</div>
<div
className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
aria-hidden="true"
>
<div
className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
</div>
</div>
)
}
export default ResultScreen;

View file

@ -1,13 +1,7 @@
'use client';
import { motion } from 'framer-motion';
import { useState } from 'react';
import LinkButton from './link-button';
const TopicCard = ({ title, children, link }: { title: string, children: any, link: string }) => {
const [clicked, setClicked] = useState( false );
const [hovered, setHovered] = useState( false );
return (
<motion.div className="mx-auto mt-16 max-w-2xl rounded-3xl sm:mt-20 lg:mx-0 lg:flex lg:max-w-none relative isolate overflow-hidden bg-gray-900 px-6 pt-16 shadow-2xl sm:rounded-3xl sm:px-16 md:pt-24 lg:flex lg:gap-x-20 lg:px-24 lg:pt-0" style={{marginTop: '20px', paddingTop: '0px', paddingBottom: '24px'}}
animate={{x: hovered? 10 : 0, opacity: clicked ? 0.5 : 1 }} onMouseEnter={()=>setHovered(true)} onMouseLeave={()=>setHovered(false)}>
const TopicCard = ({ title, children, link }) => {
return(
<div className="mx-auto mt-16 max-w-2xl rounded-3xl sm:mt-20 lg:mx-0 lg:flex lg:max-w-none relative isolate overflow-hidden bg-gray-900 px-6 pt-16 shadow-2xl sm:rounded-3xl sm:px-16 md:pt-24 lg:flex lg:gap-x-20 lg:px-24 lg:pt-0">
<svg
viewBox="0 0 1024 1024"
className="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-y-1/2 [mask-image:radial-gradient(closest-side,white,transparent)] sm:left-full sm:-ml-80 lg:left-1/2 lg:ml-0 lg:-translate-x-1/2 lg:translate-y-0"
@ -27,21 +21,23 @@ const TopicCard = ({ title, children, link }: { title: string, children: any, li
{children}
</p>
</div>
<div
className="-mt-2 p-2 lg:mt-0 lg:max-w-md lg:flex-shrink-0 lg:flex lg:flex-col lg:justify-center"
style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}
>
{/* <a
<div className="-mt-2 p-2 lg:mt-0 lg:w-full lg:max-w-md lg:flex-shrink-0">
<div className="rounded-2xl bg-gray-50 py-10 text-center ring-1 ring-inset ring-gray-900/5 lg:flex lg:flex-col lg:justify-center lg:py-16">
<div className="mx-auto max-w-xs px-8">
<p className="mt-6 flex items-baseline justify-center gap-x-2">
<span className="text-5xl font-bold tracking-tight text-gray-900">Start</span>
<span className="text-sm font-semibold leading-6 tracking-wide text-gray-900">now!</span>
</p>
<a
href={link}
className="rounded-md text-sm font-semibold border text-gray-200 shadow-sm hover:text-gray-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
style={{ paddingLeft: '50px', paddingRight: '50px', paddingTop: '20px', paddingBottom: '20px'}}
className="mt-10 block w-full rounded-md bg-indigo-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
Begin
</a> */}
<LinkButton text="Begin" href={link} onPress={()=>setClicked(true)}/>
</a>
</div>
</div>
</div>
</motion.div>
</div>
)
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -5,8 +5,8 @@ import "./globals.css";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "FlashLearn",
description: "A react based, flashcard app.",
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({

View file

@ -1,124 +0,0 @@
'use client';
import { useEffect, useState } from 'react'
import { Dialog, DialogPanel } from '@headlessui/react'
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
import Logo from '../../components/logo';
import { CheckIcon } from '@heroicons/react/20/solid';
import { SessionState } from '@/app/lib/session';
import { AnswerType, Question, getQuestions } from '@/app/lib/question';
import QuestionView from '@/app/components/question_component';
import ResultScreen from '@/app/components/results';
const shuffle = (array: any[]) => {
let i = array.length - 1;
while ( i >= 0 ) {
const random_i = Math.floor( Math.random() * i );
[array[ i ], array[ random_i ]] = [array[ random_i ], array[ i ]];
i--;
}
}
const Page = ({ params }: { params: { category: string }}) => {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
const [state, setState]: [SessionState, any] = useState<SessionState>( {
answered: 0,
wrong: 0,
right: 0,
category: '',
opened: [],
answer: []
} );
// const category = params.category;
// const [all_questions, set_all_questions] = useState<Question[]>([]);
const [questions, setQuestions] = useState<Question[]>([]);
useEffect( () => {
// console.log( params.category );
const fetch_all_questions = async () => {
let result = await getQuestions();
console.log( `all_questions: ${ JSON.stringify( result ) }` );
// set_all_questions( result );
result = result.filter( q => q.category === params.category)
.map(it=>({...it, answered: AnswerType.Unset}));
//result = result.filter
shuffle( result );
setQuestions( result );
console.log( `q12 uestions: ${ JSON.stringify( questions ) }`, result );
}
fetch_all_questions();
var ans: AnswerType[];
questions?.forEach(q => {
ans[ q.id ] = AnswerType.Unset;
});
/*
setState( (prevState: SessionState) => ({
...prevState,
answer: ans
}));
*/
}, [ params.category ]);
console.log( "questions16", questions );
console.log( "state15", state );
// alternate version (show all of them at the same time):
// {/* {questions.map( (q) => (q.answered == AnswerType.Unset) ? <QuestionView key = {q.id} question={q} state={state} setState={setState}/> : <></>)} */}
const index = state.answered;
console.log( "index18", index )
return (
<div>
<div className="relative isolate px-6 pt-14 lg:px-8">
<div style={{paddingTop: '72px'}}></div>
<Logo/>
<div
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true"
>
<div
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
<div
className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
</div>
{(()=>{
if ( !questions[ 0 ] )
return <></>;
return (index < 10 && questions[ index ]) ? <QuestionView question={questions[ index ]} state = {state} setState={setState}/> : <ResultScreen state={state}/>;
})()}
{/* {questions[ 0 ] ? ((index < 10 && questions[ index ]) ? <QuestionView question={questions[ index ]} state = {state} setState={setState}/> : <ResultScreen state={state}/>) : null} */}
<div
className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
aria-hidden="true"
>
</div>
</div>
</div>
)
}
export default Page;

View file

@ -1,87 +0,0 @@
import { CheckIcon } from '@heroicons/react/20/solid'
import TopicCard from '../components/topic_card'
import Logo from '../components/logo';
import { Transition } from '@headlessui/react';
const includedFeatures = [
'Private forum access',
'Member resources',
'Entry to annual conference',
'Official member t-shirt',
]
export default function Example() {
//List of topics
const cards = [
["Learn cybersecurity", "Learning cybersecurity is like becoming a guardian of the digital realm.\nIt's about mastering the art of protecting information, systems, and networks from cyber threats.\nFrom understanding encryption algorithms to detecting malware, every lesson equips you with tools to fortify against cyber-attacks.", "/learn/cybersec" ],
["Learn geography", "Geography is the study of our world's intricate tapestry — from the towering peaks of the Himalayas to the vast expanse of the Sahara Desert. It's about understanding the relationships between people, places, and the environment.", "/learn/geography"],
["Learn CPP", "As a powerful, versatile language, CPP teaches you the fundamentals of object-oriented programming while offering fine-grained control over system resources. You'll explore concepts like classes, inheritance, and polymorphism, alongside memory management and pointers.", "/learn/cpp"]
];
return (
<div className="py-24 sm:py-32" style = {{ alignItems: 'center', justifyContent: 'center' }}>
{/*Background*/}
<div
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true"
>
<div
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
<div
className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
</div>
{/*The logo*/}
<Logo/>
<div style={{paddingTop: '128px'}}></div>
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<Transition
appear={true}
show={true}
enter="transition-opacity duration-300"
enterFrom="opacity-0"
enterTo="opacity-80">
<div>
{ cards.map((elem) => {
return (
<TopicCard title={elem[0]} link={elem[2]}>{elem[1]}</TopicCard>
)})}
</div>
</Transition>
{/*
<TopicCard title = "Learn cybersecurity">
Learning cybersecurity is like becoming a guardian of the digital realm.
It's about mastering the art of protecting information, systems, and networks from cyber threats.
From understanding encryption algorithms to detecting malware, every lesson equips you with tools to fortify against cyber-attacks.
</TopicCard>
<TopicCard title = "Learn geography">
Learning cybersecurity is like becoming a guardian of the digital realm.
It's about mastering the art of protecting information, systems, and networks from cyber threats.
From understanding encryption algorithms to detecting malware, every lesson equips you with tools to fortify against cyber-attacks.
</TopicCard>
<TopicCard title = "Learn C++">
Learning cybersecurity is like becoming a guardian of the digital realm.
It's about mastering the art of protecting information, systems, and networks from cyber threats.
From understanding encryption algorithms to detecting malware, every lesson equips you with tools to fortify against cyber-attacks.
</TopicCard>
*/}
</div>
{/*Background*/}
<div
className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
aria-hidden="true"
>
</div>
</div>
)
}

View file

@ -1,5 +1,5 @@
// the base URL of the api; all requests start with it
const base_url: string = "https://api.phite.ro/";
const base_url: string = "http://localhost:4000/";
/*
export const makeGetRequest = async<T> (path: string): Promise<T> => {

View file

@ -1,5 +0,0 @@
const wait = (time: number): Promise<void> => {
return new Promise( res => setTimeout( res, time ) );
}
export default wait;

View file

@ -7,29 +7,18 @@ export const enum QuizQuestion {
DR
};
export const enum AnswerType {
Unset,
Right,
Wrong
};
export type Question = {
id: number;
category: string | null;
type?: string; // TODO: make a TS type for every question type
type: string | null; // TODO: make a TS type for every question type
text: string;
answer: string | boolean | QuizQuestion;
answered?: AnswerType;
}
export const getQuestion = async (id: number): Promise<Question> => {
return makeGetRequest( `questions/${id}/` );
}
export const getQuestions = async (): Promise<Question[]> => {
return makeGetRequest( `questions/` );
}
export const addQuestion = async (question: Question): Promise<Question> => {
console.log( `adding question ${JSON.stringify( question)}` );
return makePostRequest( `questions`, question );

View file

@ -1,5 +1,4 @@
import { makeGetRequest, makePostRequest } from "./api";
import { AnswerType } from "./question";
export type Session = {
id: number;
@ -9,15 +8,6 @@ export type Session = {
// user: string;
}
export type SessionState = {
answered: number;
wrong: number;
right: number;
category: string;
opened: boolean[];
answer: AnswerType[];
}
export const getSession = async (id: number): Promise<Session> => {
return makeGetRequest( `sessions/${id}/` );
}

View file

@ -1,102 +1,50 @@
'use client';
import { Fragment, useState } from 'react'
import { Fragment } from 'react'
import { Menu, MenuButton, MenuItem, MenuItems, Transition } from '@headlessui/react'
import { ChevronDownIcon } from '@heroicons/react/20/solid'
import Logo from './components/logo';
import { motion } from 'framer-motion';
import LinkButton from './components/link-button';
function classNames(...classes) {
return classes.filter(Boolean).join(' ')
}
export default function Example() {
const [buttonPressed, setButtonPressed] = useState( false );
return (
<div>
{/*Background visual elements*/}
<div
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true"
>
<div
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
<div
className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
</div>
<div style={{paddingTop: '128px'}}></div>
<Logo/>
<Transition
appear={true}
show={!buttonPressed}
enter="transition-opacity duration-500"
enterFrom="opacity-0"
enterTo="opacity-80"
leave="transition-opacity duration-150"
leaveFrom="opacity-80"
leaveTo="opacity-0">
<div className="mx-auto max-w-7xl py-24 sm:px-6 sm:py-32 lg:px-8">
<div className="relative isolate overflow-hidden bg-gray-900 px-6 pt-16 shadow-2xl sm:rounded-3xl sm:px-16 md:pt-24 lg:flex lg:gap-x-20 lg:px-24 lg:pt-0">
<svg
viewBox="0 0 1024 1024"
className="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-y-1/2 [mask-image:radial-gradient(closest-side,white,transparent)] sm:left-full sm:-ml-80 lg:left-1/2 lg:ml-0 lg:-translate-x-1/2 lg:translate-y-0"
aria-hidden="true"
>
<circle cx={512} cy={512} r={512} fill="url(#759c1415-0410-454c-8f7c-9a820de03641)" fillOpacity="0.7" />
<defs>
<radialGradient id="759c1415-0410-454c-8f7c-9a820de03641">
<stop stopColor="#7775D6" />
<stop offset={1} stopColor="#E935C1" />
</radialGradient>
</defs>
</svg>
<div className="mx-auto max-w-md text-center lg:mx-0 lg:flex-auto lg:py-32 lg:text-left">
<h2 className="text-3xl font-bold tracking-tight text-white sm:text-4xl">
Start using flash cards
<br />
Begin with our app today.
</h2>
<p className="mt-6 text-lg leading-8 text-gray-300">
Get questions from a multitude of different subjects that include cybersecurity, geography and C++
</p>
<div className="mt-10 flex items-center justify-center gap-x-6 lg:justify-start">
{/* <motion.a
href="sessionconfig"
className="rounded-md bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
style={{ marginBottom: '40px' }}
animate={{opacity: buttonHovered ? 0.8 : 1}}
onMouseEnter={()=>setButtonHovered(true)}
onMouseLeave={()=>setButtonHovered(false)}
onClick={()=>setButtonPressed(true)}
>
Get started
</motion.a> */}
<LinkButton text="Get started" href="/sessionconfig" onPress={()=>setButtonPressed(true)}/>
</div>
</div>
<div className="bg-black">
<div style={{ display:"flex", alignItems: 'center', justifyContent: 'center', paddingTop:'40px'}}><img className="flex" src="/logo-no-background.png" height="auto" width="40%" style={{ alignSelf: 'center'}}></img></div>
<div className="mx-auto max-w-7xl py-24 sm:px-6 sm:py-32 lg:px-8">
<div className="relative isolate overflow-hidden bg-gray-900 px-6 pt-16 shadow-2xl sm:rounded-3xl sm:px-16 md:pt-24 lg:flex lg:gap-x-20 lg:px-24 lg:pt-0">
<svg
viewBox="0 0 1024 1024"
className="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-y-1/2 [mask-image:radial-gradient(closest-side,white,transparent)] sm:left-full sm:-ml-80 lg:left-1/2 lg:ml-0 lg:-translate-x-1/2 lg:translate-y-0"
aria-hidden="true"
>
<circle cx={512} cy={512} r={512} fill="url(#759c1415-0410-454c-8f7c-9a820de03641)" fillOpacity="0.7" />
<defs>
<radialGradient id="759c1415-0410-454c-8f7c-9a820de03641">
<stop stopColor="#7775D6" />
<stop offset={1} stopColor="#E935C1" />
</radialGradient>
</defs>
</svg>
<div className="mx-auto max-w-md text-center lg:mx-0 lg:flex-auto lg:py-32 lg:text-left">
<h2 className="text-3xl font-bold tracking-tight text-white sm:text-4xl">
Start using flash cards
<br />
Begin with our app today.
</h2>
<p className="mt-6 text-lg leading-8 text-gray-300">
Get questions from a multitude of different subjects that include cybersecurity, geography and C++
</p>
<div className="mt-10 flex items-center justify-center gap-x-6 lg:justify-start">
<a
href="sessionconfig"
className="rounded-md bg-white px-3.5 py-2.5 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
>
Get started
</a>
</div>
</div>
</div>
</Transition>
<div
className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
aria-hidden="true"
>
<div
className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
</div>
</div>
</div>
)
}

View file

@ -1,7 +1,5 @@
import { CheckIcon } from '@heroicons/react/20/solid'
import TopicCard from '../components/topic_card'
import Logo from '../components/logo';
import { Transition } from '@headlessui/react';
const includedFeatures = [
'Private forum access',
@ -12,52 +10,20 @@ const includedFeatures = [
export default function Example() {
//List of topics
const cards = [
["Learn cybersecurity", "Learning cybersecurity is like becoming a guardian of the digital realm.\nIt's about mastering the art of protecting information, systems, and networks from cyber threats.\nFrom understanding encryption algorithms to detecting malware, every lesson equips you with tools to fortify against cyber-attacks.", "/learn/cybersec" ],
["Learn geography", "Geography is the study of our world's intricate tapestry — from the towering peaks of the Himalayas to the vast expanse of the Sahara Desert. It's about understanding the relationships between people, places and the environment.", "/learn/geography"],
["Learn CPP", "As a powerful, versatile language, C++ teaches you the fundamentals of object-oriented programming while offering fine-grained control over system resources. You'll explore concepts like classes, inheritance, and polymorphism, alongside memory management and pointers.", "/learn/cpp"]
["Learn geography", "It's cool ig", "/learn/geography"],
["Learn C++", "Don't.", "/learn/cpp"],
["Learn C", "Do.", "/learn/c"]
];
return (
<div className="py-24 sm:py-32" style = {{ alignItems: 'center', justifyContent: 'center' }}>
{/*Background*/}
<div
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
aria-hidden="true"
>
<div
className="relative left-[calc(50%-11rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-30rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
<div
className="relative left-[calc(50%+3rem)] aspect-[1155/678] w-[36.125rem] -translate-x-1/2 bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%+36rem)] sm:w-[72.1875rem]"
style={{
clipPath:
'polygon(74.1% 44.1%, 100% 61.6%, 97.5% 26.9%, 85.5% 0.1%, 80.7% 2%, 72.5% 32.5%, 60.2% 62.4%, 52.4% 68.1%, 47.5% 58.3%, 45.2% 34.5%, 27.5% 76.7%, 0.1% 64.9%, 17.9% 100%, 27.6% 76.8%, 76.1% 97.7%, 74.1% 44.1%)',
}}
/>
</div>
{/*The logo*/}
<Logo/>
<div style={{paddingTop: '128px'}}></div>
<div className="bg-black py-24 sm:py-32">
<div style={{ display:"flex", alignItems: 'center', justifyContent: 'center', paddingTop:'40px'}}><img className="flex" src="/logo-no-background.png" height="auto" width="40%" style={{ alignSelf: 'center'}}></img></div>
<div className="mx-auto max-w-7xl px-6 lg:px-8">
<Transition
appear={true}
show={true}
enter="transition-opacity duration-300"
enterFrom="opacity-0"
enterTo="opacity-80">
<div>
{ cards.map((elem) => {
return (
<TopicCard title={elem[0]} link={elem[2]}>{elem[1]}</TopicCard>
)})}
</div>
</Transition>
{ cards.map((elem) => {
return (<TopicCard title={elem[0]} link={elem[2]}>{elem[1]}</TopicCard>)
})}
{/*
<TopicCard title = "Learn cybersecurity">
Learning cybersecurity is like becoming a guardian of the digital realm.
@ -76,12 +42,6 @@ export default function Example() {
</TopicCard>
*/}
</div>
{/*Background*/}
<div
className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
aria-hidden="true"
>
</div>
</div>
)
}

40
package-lock.json generated
View file

@ -10,11 +10,9 @@
"dependencies": {
"@headlessui/react": "^2.0.4",
"@heroicons/react": "^2.1.3",
"framer-motion": "^11.2.10",
"next": "14.2.3",
"react": "^18",
"react-dom": "^18",
"react-use-wizard": "^2.3.0"
"react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",
@ -2246,30 +2244,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/framer-motion": {
"version": "11.2.10",
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.2.10.tgz",
"integrity": "sha512-/gr3PLZUVFCc86a9MqCUboVrALscrdluzTb3yew+2/qKBU8CX6nzs918/SRBRCqaPbx0TZP10CB6yFgK2C5cYQ==",
"dependencies": {
"tslib": "^2.4.0"
},
"peerDependencies": {
"@emotion/is-prop-valid": "*",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"peerDependenciesMeta": {
"@emotion/is-prop-valid": {
"optional": true
},
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@ -3937,18 +3911,6 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true
},
"node_modules/react-use-wizard": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/react-use-wizard/-/react-use-wizard-2.3.0.tgz",
"integrity": "sha512-z06pQNZ18FvoK+ZDW50hOf0uOySo0Hhd7H4y0MLyk/tBCwpUKGBeULosORBVhipUaWihNLpLJxwH5f+85Qt5XA==",
"engines": {
"node": ">=10"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",

View file

@ -11,11 +11,9 @@
"dependencies": {
"@headlessui/react": "^2.0.4",
"@heroicons/react": "^2.1.3",
"framer-motion": "^11.2.10",
"next": "14.2.3",
"react": "^18",
"react-dom": "^18",
"react-use-wizard": "^2.3.0"
"react-dom": "^18"
},
"devDependencies": {
"@types/node": "^20",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB