diff --git a/.babelrc b/.babelrc
new file mode 100644
index 00000000..b085c21c
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+ "presents": ["@babel/present-env"]
+}
\ No newline at end of file
diff --git a/.babelrc.json b/.babelrc.json
new file mode 100644
index 00000000..92e4ea82
--- /dev/null
+++ b/.babelrc.json
@@ -0,0 +1,5 @@
+{
+ "presets": [...],
+ "plugins": [...]
+ }
+{ "extends": "../../.babelrc" }
\ No newline at end of file
diff --git a/.browserslistrc b/.browserslistrc
new file mode 100644
index 00000000..bd9fb772
--- /dev/null
+++ b/.browserslistrc
@@ -0,0 +1,2 @@
+> 0.25%
+not dead
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 9a382ba3..14ba685c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,4 +22,7 @@ package-lock.json
*.ntvs*
*.njsproj
*.sln
-*.sw?
\ No newline at end of file
+*.sw?
+.env
+# Local Netlify folder
+.netlify
diff --git a/.idx/dev.nix b/.idx/dev.nix
new file mode 100644
index 00000000..b13048f6
--- /dev/null
+++ b/.idx/dev.nix
@@ -0,0 +1,30 @@
+{pkgs}: {
+ channel = "stable-24.05";
+ packages = [
+ pkgs.nodejs_20
+ pkgs.python312Packages.pip
+ pkgs.busybox
+ pkgs.nox
+ ];
+ idx.extensions = [
+ "svelte.svelte-vscode"
+ "vue.volar"
+ ];
+ idx.previews = {
+ previews = {
+ web = {
+ command = [
+ "npm"
+ "run"
+ "dev"
+ "--"
+ "--port"
+ "$PORT"
+ "--host"
+ "0.0.0.0"
+ ];
+ manager = "web";
+ };
+ };
+ };
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 200f4282..0c6d145e 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,6 @@
-# Portfolio
+#Global-Tech-Portfolio
+A/RES/217(III)
+A/RES/70/1
+GDPR EU 2016/679
+The AI Act
+WCAG
\ No newline at end of file
diff --git a/To b/To
new file mode 100644
index 00000000..e69de29b
diff --git a/[ b/[
new file mode 100644
index 00000000..1de0c549
--- /dev/null
+++ b/[
@@ -0,0 +1 @@
+more is not installed, but available in the following packages, pick one to run it, Ctrl+C to cancel.
diff --git a/a.js b/a.js
new file mode 100644
index 00000000..9c730bc0
--- /dev/null
+++ b/a.js
@@ -0,0 +1,4 @@
+var a = new Promise();
+import "core-js/modules/es.promise";
+var a = new Promise();
+var a = new Promise();
\ No newline at end of file
diff --git a/api.ts b/api.ts
new file mode 100644
index 00000000..60f9b523
--- /dev/null
+++ b/api.ts
@@ -0,0 +1,154 @@
+import React, { StrictMode } from 'react';
+import ReactDOM from 'react-dom';
+import styled, { ThemeProvider, DefaultTheme } from 'styled-components';
+
+declare module 'styled-components' {
+ export interface DefaultTheme {
+ color?: string;
+ bg?: string;
+ }
+}
+import { createRoot } from 'react-dom/client'
+
+const Button = styled.button`
+ background: #BF4F74;
+ border-radius: 3px;
+ border: none;
+ color: white;
+`
+
+const TomatoButton = styled(Button)`
+ background: tomato;
+`
+
+const container1 = document.createElement('div');
+document.body.appendChild(container1);
+
+const root1 = createRoot(container1);
+root1.render(
+
+ <>
+ I'm purple.
+
+ I'm red.
+ >
+
+);
+// import styled from 'styled-components'
+
+const padding = '3em'
+
+const Section = styled.section<{ $background?: string; }>`
+ color: white;
+
+ /* Pass variables as inputs */
+ padding: ${padding};
+ background: ${(props) => props.$background || 'transparent'};
+ `;
+
+const container2 = document.createElement('div');
+document.body.appendChild(container2);
+
+const root2 = createRoot(container2);
+root2.render(
+
+
+ alert('It works!')}>
+ Click Me!
+
+
+ Hello Recruiter!
+
+
+ Drag me!
+
+
+ Drag Me!
+
+
+
+ );
+// import styled from 'styled-components'
+
+const Input = styled.input.attrs<{ padding?: string | number; small?: boolean }>((props) => ({
+ small: props.small || false,
+ type: 'text',
+ size: props.small ? 5 : undefined,
+}))<{ padding?: string | number; small?: boolean }>`
+ border-radius: 3px;
+ border: 1px solid #BF4F74;
+ display: block;
+ margin: 0 0 1em;
+ padding: ${(props) => (typeof props.padding === 'number' ? `${props.padding}em` : props.padding)};
+
+ ::placeholder {
+ ::placeholder {
+ color: #BF4F74;
+ }
+ `;
+ `;
+
+ // Ensure the target element exists in the HTML file
+ const rootElement = document.getElementById('root');
+ ReactDOM.render(
+
+
+
+ ,
+ rootElement
+ );
+ rootElement
+// Removed extraneous closing brace
+// import styled from "styled-components";
+
+const Component = styled.div`
+ color: red;
+`;
+ alert('It works!')}
+>
+ {/* Removed duplicate render call and fixed syntax */}
+
+ {/* Removed duplicate render call and fixed syntax */}
+
+
+// Removed duplicate and incomplete render logic
+// Removed duplicate render call
+ // Removed redundant line
+ // import styled, { ThemeProvider } from 'styled-components'
+
+const Box1 = styled.div`
+ color: ${(props) => props.theme?.color || 'black'};
+`;
+
+const rootElement1 = document.getElementById('root');
+if (rootElement1) {
+ const root1 = createRoot(rootElement1);
+ root1.render(
+
+ {"I'm mediumseagreen!"}
+
+);
+
+// import styled, { ThemeProvider } from 'styled-components'
+ // Removed incomplete and unused statement
+);
+
+const Box2 = styled.div`
+ background: ${(props) => props.theme?.bg || 'transparent'};
+`;
+const rootElement = document.getElementById('root');
+const rootElement2 = document.getElementById('root');
+if (rootElement2) {
+ const root2 = createRoot(rootElement2);
+ root2.render(
+
+
+ {"I'm mediumseagreen with a white background!"}
+
+
+ );
+
+ );
+}
diff --git a/app.js b/app.js
new file mode 100644
index 00000000..a0d75618
--- /dev/null
+++ b/app.js
@@ -0,0 +1,68 @@
+require('dotenv').config();
+
+var createError = require('http-errors');
+var express = require('express');
+var path = require('path');
+var cookieParser = require('cookie-parser');
+var logger = require('morgan');
+var logger = require('morgan');
+var session = require('express-session');
+var session = require('express-session');
+var passport = require('passport');
+var SQLiteStore = require('connect-sqlite3')(session);
+var session = require('express-session');
+var passport = require('passport');
+var SQLiteStore = require('connect-sqlite3')(session);
+var indexRouter = require('./routes/index');
+
+var authRouter = require('./routes/auth');
+
+var app = express();
+
+app.locals.pluralize = require('pluralize');
+
+// view engine setup
+app.set('views', path.join(__dirname, 'views'));
+app.set('view engine', 'ejs');
+
+app.use(logger('dev'));
+app.use(express.json());
+app.use(express.urlencoded({ extended: false }));
+app.use(cookieParser());
+app.use('/', indexRouter);
+app.use('/', authRouter);
+app.use(express.static(path.join(__dirname, 'public')));
+app.use(express.static(path.join(__dirname, 'public')));
+
+app.use(session({
+ secret: 'keyboard cat',
+ resave: false,
+ saveUninitialized: false,
+ store: new SQLiteStore({ db: 'sessions.db', dir: './var/db' })
+}));
+app.use('/', indexRouter);
+app.use('/', authRouter);
+app.use(session({
+ secret: 'keyboard cat',
+ resave: false,
+ saveUninitialized: false,
+ store: new SQLiteStore({ db: 'sessions.db', dir: './var/db' })
+}));
+app.use(passport.authenticate('session'));
+// catch 404 and forward to error handler
+app.use(function(req, res, next) {
+ next(createError(404));
+});
+
+// error handler
+app.use(function(err, req, res, next) {
+ // set locals, only providing error in development
+ res.locals.message = err.message;
+ res.locals.error = req.app.get('env') === 'development' ? err : {};
+
+ // render the error page
+ res.status(err.status || 500);
+ res.render('error');
+});
+
+module.exports = app;
diff --git a/autorestic b/autorestic
new file mode 100755
index 00000000..fe6fccb2
Binary files /dev/null and b/autorestic differ
diff --git a/b.js b/b.js
new file mode 100644
index 00000000..a8ebb503
--- /dev/null
+++ b/b.js
@@ -0,0 +1,4 @@
+var b = new Map();
+import "core-js/modules/es.map";
+var b = new Map();
+var b = new Map();
\ No newline at end of file
diff --git a/babel-plugin.js b/babel-plugin.js
new file mode 100644
index 00000000..7600b355
--- /dev/null
+++ b/babel-plugin.js
@@ -0,0 +1,28 @@
+// a naive plugin replace `a.b` to `a != null && a.b`
+module.exports = api => {
+ const targets = api.targets();
+ // The targets have native optional chaining support
+ // if `transform-optional-chaining` is _not_ required
+ const optionalChainingSupported = !isRequired(
+ "transform-optional-chaining",
+ targets
+ );
+ const visited = new WeakSet();
+ return {
+ visitor: {
+ MemberExpression(path) {
+ if (path.matchesPattern("a.b")) {
+ if (visited.has(path.node)) return;
+ visited.add(path.node);
+ if (optionalChainingSupported) {
+ // When optional chaining is supported,
+ // output `a?.b` instead of `a != null && a.b`
+ path.replaceWith(api.templates`a?.b`);
+ } else {
+ path.replaceWith(api.templates`a != null && ${path.node}`);
+ }
+ }
+ },
+ },
+ };
+ };
\ No newline at end of file
diff --git a/babel.config.json b/babel.config.json
new file mode 100644
index 00000000..3ea64140
--- /dev/null
+++ b/babel.config.json
@@ -0,0 +1,398 @@
+{
+ "presets": [
+ [
+ "@babel/preset-env",
+ {
+ "targets": {
+ "edge": "17",
+ "firefox": "60",
+ "chrome": "67",
+ "safari": "11.1"
+ },
+ "useBuiltIns": "usage",
+ "corejs": "3.6.5"
+ }
+ ]
+ ]
+ }
+const presets = [
+ [
+ "@babel/preset-env",
+ {
+ targets: {
+ edge: "17",
+ firefox: "60",
+ chrome: "67",
+ safari: "11.1",
+ },
+ useBuiltIns: "usage",
+ corejs: "3.6.4",
+ },
+ ],
+ ];
+
+ module.exports = { presets };
+{
+ "presets": [
+ [
+ "@babel/preset-env",
+ {
+ "targets": {
+ "edge": "17",
+ "firefox": "60",
+ "chrome": "67",
+ "safari": "11.1"
+ }
+ }
+ ]
+ ]
+ }
+{
+ "presets": [
+ [
+ "@babel/preset-env",
+ {
+ "targets": {
+ "edge": "17",
+ "firefox": "60",
+ "chrome": "67",
+ "safari": "11.1"
+ },
+ "useBuiltIns": "usage"
+ }
+ ]
+ ]
+ }
+{
+ "presets": [
+ [
+ "@babel/preset-env",
+ {
+ "targets": {
+ "edge": "17",
+ "firefox": "60",
+ "chrome": "67",
+ "safari": "11.1"
+ },
+ "useBuiltIns": "entry"
+ }
+ ]
+ ]
+ }
+{
+ "presets": [...],
+ "plugins": [...]
+ }
+module.exports = function (api) {
+ api.cache(true);
+
+ const presets = [ ... ];
+ const plugins = [ ... ];
+
+ return {
+ presets,
+ plugins
+ };
+ }
+babel.config.js
+module.exports = function (api) {
+ api.cache(true);
+
+ const presets = [ ... ];
+ const plugins = [ ... ];
+
+ if (process.env["ENV"] === "prod") {
+ plugins.push(...);
+ }
+
+ return {
+ presets,
+ plugins
+ };
+}
+module.exports = {
+ presets: ["@babel/env"], // "@babel/preset-env"
+ plugins: ["@babel/transform-arrow-functions"], // same as "@babel/plugin-transform-arrow-functions"
+ };
+{
+ "plugins": ["@babel/plugin-transform-runtime"]
+ }
+module.exports = function(api) {
+ return {};
+ };
+{
+ "targets": "> 0.25%, not dead"
+ }
+{
+ "targets": {
+ "chrome": "58",
+ "ie": "11"
+ }
+ }
+{
+ "presets": ["@babel/preset-env"]
+ }
+{
+ "targets": "defaults"
+ }
+{
+ // Resolve to "Chrome 61+, FF60+, Safari 11+"
+ "targets": {
+ "esmodules": "intersect", // Chrome 61+, FF 60+, Safari 10.1+
+ "browsers": "chrome 58, firefox 60, safari 11"
+ }
+ }
+{
+ "targets": "node 12" // not recommended
+ }
+{
+ "targets": "node 12.0"
+ }
+{
+ "targets": {
+ "deno": "1.9"
+ }
+ }
+{
+ "assumptions": {
+ "iterableIsArray": true
+ },
+ "presets": ["@babel/preset-env"]
+ }
+{
+ "plugins": ["babel-plugin-myPlugin", "@babel/plugin-transform-runtime"]
+ }
+{
+ "plugins": ["./node_modules/asdf/plugin"]
+ }
+{
+ "plugins": ["transform-decorators-legacy", "transform-class-properties"]
+ }
+{
+ "presets": ["@babel/preset-env", "@babel/preset-react"]
+ }
+{
+ "plugins": ["pluginA", ["pluginA"], ["pluginA", {}]]
+ }
+{
+ "plugins": [
+ [
+ "transform-async-to-module-method",
+ {
+ "module": "bluebird",
+ "method": "coroutine"
+ }
+ ]
+ ]
+ }
+{
+ "presets": [
+ [
+ "env",
+ {
+ "loose": true,
+ "modules": false
+ }
+ ]
+ ]
+ }
+{
+ "targets": ">0.5%",
+ "assumptions": {
+ "noDocumentAll": true,
+ "noClassCalls": true
+ },
+ "presets": ["@babel/preset-env"]
+ }
+{
+ "presets": ["babel-preset-myPreset", "@babel/preset-env"]
+ }
+{
+ "presets": ["./myProject/myPreset"]
+ }
+{
+ "presets": ["a", "b", "c"]
+ }
+{
+ "presets": [
+ "presetA", // bare string
+ ["presetA"], // wrapped in array
+ ["presetA", {}] // 2nd argument is an empty options object
+ ]
+}
+{
+ "presets": [
+ [
+ "@babel/preset-env",
+ {
+ "loose": true,
+ "modules": false
+ }
+ ]
+ ]
+ }
+{
+ "presets": [
+ [
+ "@babel/preset-env",
+ {
+ "useBuiltIns": "entry",
+ "corejs": "3.22"
+ }
+ ]
+ ]
+ }
+{
+ "plugins": ["@babel/plugin-transform-explicit-resource-management"]
+ }
+{
+ "plugins": ["@babel/plugin-transform-duplicate-named-capturing-groups-regex"]
+ }
+{
+ "plugins": ["@babel/plugin-transform-json-modules"]
+ }
+{
+ "plugins": ["@babel/plugin-transform-regexp-modifiers"]
+ }
+{
+ "plugins": ["@babel/plugin-syntax-import-attributes"]
+ }
+ {
+ "plugins": ["@babel/plugin-bugfix-firefox-class-in-computed-class-key"]
+ }
+ {
+ "plugins": ["@babel/plugin-bugfix-safari-class-field-initializer-scope"]
+ }
+ {
+ "plugins": ["@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression"]
+ }
+ {
+ "plugins": ["@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining"]
+ }
+ {
+ "presets": ["@babel/preset-react"]
+ }
+ {
+ "presets": [
+ [
+ "@babel/preset-react",
+ {
+ "pragma": "dom", // default pragma is React.createElement (only in classic runtime)
+ "pragmaFrag": "DomFrag", // default is React.Fragment (only in classic runtime)
+ "throwIfNamespace": false, // defaults to true
+ "runtime": "classic" // defaults to classic
+ // "importSource": "custom-jsx-library" // defaults to react (only in automatic runtime)
+ }
+ ]
+ ]
+ }
+ babel.config.js
+module.exports = {
+ presets: [
+ [
+ "@babel/preset-react",
+ {
+ development: process.env.BABEL_ENV === "development",
+ },
+ ],
+ ],
+};
+{
+ "presets": ["@babel/preset-react"],
+ "env": {
+ "development": {
+ "presets": [["@babel/preset-react", { "development": true }]]
+ }
+ }
+ }
+ {
+ "plugins": ["@babel/plugin-transform-react-jsx"]
+ }
+ {
+ "plugins": [
+ [
+ "@babel/plugin-transform-react-jsx",
+ {
+ "throwIfNamespace": false, // defaults to true
+ "runtime": "automatic", // defaults to classic
+ "importSource": "custom-jsx-library" // defaults to react
+ }
+ ]
+ ]
+ }
+ {
+ "plugins": ["@babel/plugin-transform-react-jsx-development"]
+ }
+ {
+ "plugins": [
+ [
+ "@babel/plugin-transform-react-jsx-development",
+ {
+ "throwIfNamespace": false, // defaults to true
+ "runtime": "automatic", // defaults to classic
+ "importSource": "custom-jsx-library" // defaults to react
+ }
+ ]
+ ]
+ }
+ {
+ "presets": ["@babel/preset-typescript"]
+ }
+ {
+ "presets": ["@babel/preset-react"],
+ "overrides": [{
+ "test": "*.vue",
+ "presets": [
+ ["@babel/preset-typescript"], { "ignoreExtensions": true }
+ ]
+ }]
+ }
+ {
+ "presets": [
+ ["@babel/preset-typescript", {
+ "rewriteImportExtensions": true
+ }]
+ ]
+ }
+ {
+ "plugins": ["@babel/plugin-transform-typescript"]
+ }
+ {
+ "presets": ["@babel/preset-flow"]
+ }
+ {
+ "plugins": ["@babel/plugin-transform-flow-strip-types"]
+ }
+ {
+ "plugins": ["@babel/plugin-transform-runtime"]
+ }
+ {
+ "plugins": [
+ [
+ "@babel/plugin-transform-runtime",
+ {
+ "absoluteRuntime": false,
+ "corejs": false,
+ "helpers": true,
+ "regenerator": true,
+ "version": "7.0.0-beta.0"
+ }
+ ]
+ ]
+ }
+ {
+ "plugins": [
+ ["@babel/plugin-transform-runtime", {
+ "version": "^7.24.0"
+ }]
+ ]
+ }
+ module.exports = api => {
+ const targets = api.targets();
+ // The targets have native optional chaining support
+ // if `transform-optional-chaining` is _not_ required
+ const optionalChainingSupported = !isRequired(
+ "transform-optional-chaining",
+ targets
+ );
+ };
\ No newline at end of file
diff --git a/backend/db.js b/backend/db.js
new file mode 100644
index 00000000..a583076f
--- /dev/null
+++ b/backend/db.js
@@ -0,0 +1,32 @@
+import mongoose from 'mongoose';
+
+const { Schema } = mongoose;
+
+// Define the schema for our blog post
+const blogSchema = new Schema({
+ title: String, // String is shorthand for {type: String}
+ author: String,
+ body: String,
+ comments: [{ body: String, date: Date }],
+ date: { type: Date, default: Date.now },
+ hidden: Boolean,
+ meta: {
+ votes: Number,
+ favs: Number
+ }
+});
+
+// Create a model from the schema
+const Blog = mongoose.model('Blog', blogSchema);
+
+// Function to connect to the database
+async function main() {
+ await mongoose.connect('mongodb://127.0.0.1:27017/test');
+ // use `await mongoose.connect('mongodb://user:password@127.0.0.1:27017/test');` if your database has auth enabled
+}
+
+// Connect to the database
+main().catch(err => console.log(err));
+
+// Export the model for use in other parts of the application
+export default Blog;
diff --git a/backend/package.json b/backend/package.json
new file mode 100644
index 00000000..887b75ff
--- /dev/null
+++ b/backend/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "project-global-tech-portfolio-backend",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "main": "server.js",
+ "scripts": {
+ "start": "babel-node server.js",
+ "dev": "nodemon server.js --exec babel-node"
+ },
+ "author": "Code-lab-web",
+ "license": "(ISC OR GPL-3.0)",
+ "dependencies": {
+ "@babel/core": "^7.8.3",
+ "@babel/node": "^7.23.9",
+ "@babel/preset-env": "^7.8.3",
+ "nodemon": "^3.1.10"
+ }
+}
diff --git a/backend/server.js b/backend/server.js
new file mode 100644
index 00000000..29921db9
--- /dev/null
+++ b/backend/server.js
@@ -0,0 +1,148 @@
+import express from 'express'
+import bodyParser from 'body-parser'
+import cors from 'cors'
+import crypto from 'crypto'
+import mongoose from 'mongoose'
+import bcrypt from 'bcrypt-nodejs'
+import dotenv from 'dotenv'
+
+dotenv.config()
+
+const mongoUrl =process.env_MONGO_URL II "mongodb://localhost/auth",
+mongoose.connect(mongoUrl, { useNewUrlParser: true, useundefinedtopology: true})
+mongoose.Promise = Promise
+
+const { Schema, model } = mongoose
+const userSchema = new Schema({
+
+const User = mongoose.model('User', {
+ name: {
+ type: String,
+ unique: true
+ },
+ password:{
+ type:String,
+ required:true
+ },
+ accessToken:{
+ type:String,
+ default: () => crypto.randomBytes(128)toString('hex')
+ }
+ });
+ const User = model("User", userSchema)
+
+ // Example
+ // POST Request
+ const request = {name: "Bob", password: "foobar};
+ // DB Entry
+ const dbEntry = {name :"Bob, password:"5abbc32983def"}
+ bcrypt.compareSync(request.password, dbEntry.password);
+ // One-way encryption
+const user = new User({name:"Bob", password:bcrypt.hashSync("foobar")});
+user.save();
+// Defines the port the app will run on. Defaults to 8080, but can be overritten when starting the server. For example:
+//
+// PORT-9000 npm start
+const port = process.env.PORT II 8080
+const app = express()
+const authenticateUser = async (req, res, next) => {
+ const user = await User.findOne({accesToken: req.header('Authorization')});
+ if(user){
+ req.user = user;
+ next();
+ {else{
+res.status(401).json({loggedOut:true});
+ }}
+ }
+}
+
+// Add middlewares to enable cors and json body parsing
+app.use(cors())
+app.use(express.json());
+app.use(bodyParser.json())
+
+// Start defining your routes here
+app.get('/', (req, res) => {
+ res.send('Hello Member')
+ app.post('/tweets' authenticateUser);
+ app.post('/tweets', async (req,res) =>{
+ // This will only happen if the next() function is called from middleware!
+ // now we can access the req.user object from the middleware
+ })
+
+ }
+ })
+})
+
+// Start defining your routes here
+app.get('/,(req, res) => {
+ res.send('Hello world')
+})
+app.post('/sessions' async (req res) => {
+ const user = await User.findOne({name: req.body.name});
+ if(user && bcrypt.compareSync(req.body.password, user.password)){
+ // Success
+ res.json({userId: user._id, accessToken}};
+ }else{
+ // Failure
+ // a.User does not exist
+ // b. Encrypted password does not march
+ res.json({notFound: true});
+ }
+ }
+});
+app.post("/users", (req, res) => {
+ try {
+ const { name, email, password } = req.body
+ const salt = bcrypt.genSaltSync()
+ const user = new User({ name, email, password: bcrypt.hashSync(password, salt) })
+ user.save()
+ res.status(201).json({
+ success: true,
+ message: "User created",
+ id: user._id,
+ accessToken: user.accessToken,
+ })
+ } catch (error) {
+ res.status(400).json({
+ success: false,
+ message: "Could not create user",
+ errors: error
+ })
+ }
+ })
+
+ app.get("/secrets", authenticateUser)
+app.get("/secrets", (req, res) => {
+ res.json({
+ secret: "This is secret"
+ app.get('/secrets', (req, res) =>{
+ res.jsons({secret: 'This is a super secret message'})
+ });
+ }
+ app.post('/sessions' async (req, res) => {
+ const user = await User.findOne({email: req.body.email});
+ if (user && bcrypt.compareSync(req.body.password. user.password)){
+ res.json({userId: user_Id, assessToken: user.accessToken});
+ }else{
+ res.json({notFound: true});
+
+// Add middlewares to enable cors and json body parsing
+app.use(cors())
+app.use(bodyParser.json())
+//Start defing your routes here
+app.get('/',(req, res) => {
+ //fetch('...,{headers:{Authorization:
+ 'my secret apt key'}}}
+ res.send{process.env.API_KEY}})
+}
+
+
+
+// Start the server
+})
+app.listen(port, () => {
+ console.log('Server running on http://localhost:${port}')
+})
+ console.log(bcrypt.hashSync("foobar"));
+})
\ No newline at end of file
diff --git a/collect-await-expression.plugin.js b/collect-await-expression.plugin.js
new file mode 100644
index 00000000..9c29cb8a
--- /dev/null
+++ b/collect-await-expression.plugin.js
@@ -0,0 +1,25 @@
+module.exports = (api) => {
+ const { types: t, traverse } = api;
+ return {
+ name: "collect-await",
+ visitor: {
+ Function(path) {
+ if (path.node.async) {
+ const awaitExpressions = [];
+ // Get a list of related await expressions within the async function body
+ path.traverse(traverse.visitors.merge([
+ environmentVisitor,
+ {
+ AwaitExpression(path) {
+ awaitExpressions.push(path);
+ },
+ ArrowFunctionExpression(path) {
+ path.skip();
+ },
+ }
+ ]))
+ }
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/cpython b/cpython
new file mode 160000
index 00000000..cb624ce5
--- /dev/null
+++ b/cpython
@@ -0,0 +1 @@
+Subproject commit cb624ce53d526700e82b8eadc180310f9d47e970
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 00000000..6a10b2c5
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,120 @@
+import babelParser from "@babel/eslint-parser";
+import { defineConfig } from "eslint/config";
+
+export default defineConfig([
+ {
+ files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
+ languageOptions: {
+ parser: babelParser,
+ },
+ },
+]);
+import babelParser from "@babel/eslint-parser";
+import { defineConfig } from "eslint/config";
+
+export default defineConfig([
+ {
+ files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
+ languageOptions: {
+ parser: babelParser,
+ parserOptions: {
+ requireConfigFile: false,
+ babelOptions: {
+ babelrc: false,
+ configFile: false,
+ // your babel options
+ presets: ["@babel/preset-env"],
+ },
+ },
+ },
+ },
+]);
+import babelParser from "@babel/eslint-parser";
+import { defineConfig } from "eslint/config";
+
+export default defineConfig([
+ {
+ files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
+ languageOptions: {
+ parser: babelParser,
+ parserOptions: {
+ requireConfigFile: false,
+ babelOptions: {
+ babelrc: false,
+ configFile: "path/to/babel.config.js",
+ },
+ },
+ },
+ },
+]);
+import babelParserExperimentalWorker from "@babel/eslint-parser/experimental-worker";
+import { defineConfig } from "eslint/config";
+
+export default defineConfig([
+ {
+ files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
+ languageOptions: {
+ parser: babelParserExperimentalWorker,
+ parserOptions: {
+ requireConfigFile: false,
+ babelOptions: {
+ babelrc: false,
+ configFile: "path/to/babel.config.mjs",
+ },
+ },
+ },
+ },
+]);
+import babelParser from "@babel/eslint-parser";
+import { defineConfig } from "eslint/config";
+
+export default defineConfig([
+ {
+ files: ["files/transformed/by/babel/*.js"],
+ languageOptions: {
+ parser: babelParser,
+ },
+ },
+]);
+import babelParser from "@babel/eslint-parser";
+import { defineConfig } from "eslint/config";
+
+export default defineConfig([
+ {
+ files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
+ languageOptions: {
+ parser: babelParser,
+ parserOptions: {
+ babelOptions: {
+ rootMode: "upward",
+ },
+ },
+ },
+ },
+]);
+import babelParser from "@babel/eslint-parser";
+import babelPlugin from "@babel/eslint-plugin";
+import { defineConfig } from "eslint/config";
+
+export default defineConfig([
+ {
+ files: ["**/*.js", "**/*.cjs", "**/*.mjs"],
+ languageOptions: {
+ parser: babelParser,
+ },
+ plugins: {
+ babel: babelPlugin
+ },
+ rules: {
+ "new-cap": "off",
+ "no-undef": "off",
+ "no-unused-expressions": "off",
+ "object-curly-spacing": "off",
+
+ "babel/new-cap": "error",
+ "babel/no-undef": "error",
+ "babel/no-unused-expressions": "error",
+ "babel/object-curly-spacing": "error"
+ }
+ },
+]);
\ No newline at end of file
diff --git a/facebook-tutorial b/facebook-tutorial
new file mode 160000
index 00000000..e463820b
--- /dev/null
+++ b/facebook-tutorial
@@ -0,0 +1 @@
+Subproject commit e463820b61c09f3d3ad79fccb9c5ca01bff75e4e
diff --git a/frontend/components/App.css b/frontend/components/App.css
new file mode 100644
index 00000000..83bc46b0
--- /dev/null
+++ b/frontend/components/App.css
@@ -0,0 +1,661 @@
+@import "tailwindcss";
+/* This file should only contain CSS rules. */
+const App =() => {
+ return {
+ <>
+
+ }
+}
+@media (min-width: 320px) {
+ body {
+ width: 100%;
+ }
+}
+
+@media (max-width: 1600px) {
+ body {
+ width: 100%;
+ }
+}
+/* Add your CSS styles here */
+* Base styles with accessibility considerations */
+:root {
+ --primary-color: #2c3e50;
+ --background-color: #ffffff;
+ --accent-color: #0040a3; /* Darker blue for better contrast */
+ --error-color: #e74c3c;
+ --success-color: #27ae60;
+ --focus-outline: 3px solid var(--accent-color);
+ --focus-ring-color: rgba(0, 86, 179, 0.5);
+ --progress-bg: #edf2f7;
+ --modal-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
+}
+
+/* Apply box-sizing border-box to all elements */
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+/* Modal Dialog */
+.modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.6);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+ backdrop-filter: blur(4px);
+}
+
+/* Ensure hidden attribute works properly */
+.modal[hidden] {
+ display: none;
+}
+
+.modal-content {
+ background-color: var(--background-color);
+ padding: 2rem;
+ border-radius: 8px;
+ max-width: 500px;
+ width: 90%;
+ max-height: 90vh;
+ overflow-y: auto;
+ box-shadow: var(--modal-shadow);
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ animation: modalAppear 0.3s ease-out;
+}
+
+@keyframes modalAppear {
+ from {
+ opacity: 0;
+ transform: translateY(-20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+/* Checkbox styling */
+.checkbox-container {
+ display: flex;
+ align-items: center;
+ margin-bottom: 0.5rem;
+}
+
+.checkbox-container input[type='checkbox'] {
+ width: auto;
+ margin-right: 0.5rem;
+}
+
+select {
+ width: 100%;
+ padding: 0.5rem;
+ font-size: 1rem;
+ border: 1px solid var(--secondary-color);
+ border-radius: 4px;
+}
+
+.checkbox-container label {
+ margin-bottom: 0;
+}
+.modal-body {
+ margin: 1.5rem 0;
+}
+
+.intro-section {
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.modal-footer {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 2rem;
+ gap: 1rem;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+ padding-top: 1.5rem;
+}
+
+#modal-title {
+ color: var(--primary-color);
+ margin: 0 0 1rem 0;
+ font-size: 1.5rem;
+ font-weight: 600;
+}
+
+.modal button {
+ padding: 0.75rem 1.5rem;
+ border-radius: 6px;
+ font-size: 1rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+#save-settings {
+ background-color: var(--accent-color);
+ color: white;
+ border: none;
+}
+
+#save-settings:hover {
+ background-color: #004494;
+}
+
+#close-modal {
+ background-color: transparent;
+ border: 1px solid var(--primary-color);
+ color: var(--primary-color);
+}
+
+#close-modal:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+
+/* Base styles for readability */
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial,
+ sans-serif;
+ line-height: 1.6;
+ color: var(--primary-color);
+ background-color: var(--background-color);
+ margin: 0;
+ padding: 20px;
+ font-size: 16px;
+ max-width: 800px;
+ margin: 0 auto;
+}
+
+/* Skip link with enhanced visibility */
+.skip-link {
+ position: absolute;
+ top: -40px;
+ left: 0;
+ background: var(--accent-color);
+ color: white;
+ padding: 8px;
+ z-index: 100;
+ transition: top 0.3s;
+}
+
+.skip-link:focus {
+ top: 0;
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+}
+
+/* Enhanced focus styles */
+:focus-visible {
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+ border-radius: 2px;
+}
+
+/* Progress bar styles */
+.quiz-progress {
+ margin: 2rem 0;
+}
+/* Images */
+.decorative-image,
+.info-image {
+ max-width: 15rem;
+ height: auto;
+ margin: 1rem 0;
+ border-radius: 4px;
+}
+
+.progress-bar {
+ background-color: var(--progress-bg);
+ border-radius: 8px;
+ height: 20px;
+ overflow: hidden;
+ position: relative;
+}
+
+.progress-fill {
+ background-color: var(--accent-color);
+ height: 100%;
+ transition: width 0.3s ease;
+ border-radius: 8px;
+}
+
+.progress-text {
+ margin-top: 0.5rem;
+ text-align: center;
+ font-weight: 500;
+}
+
+/* Question groups */
+.question-group {
+ margin-bottom: 2rem;
+ padding: 1rem;
+ border: 1px solid #e2e8f0;
+ border-radius: 8px;
+ background-color: #f8fafc;
+}
+
+.question-heading {
+ color: var(--primary-color);
+ margin-bottom: 1rem;
+ font-size: 1.1rem;
+}
+
+/* Form elements */
+fieldset {
+ border: 1px solid var(--primary-color);
+ margin: 1em 0;
+ padding: 1em;
+ border-radius: 4px;
+}
+
+legend {
+ font-weight: bold;
+ padding: 0.5em 1em;
+ color: var(--primary-color);
+ background-color: #f8fafc;
+ border: 1px solid var(--primary-color);
+ border-radius: 4px;
+}
+
+.radio-group {
+ margin: 1em 0;
+}
+
+/* Enhanced radio button styling */
+.radio-option {
+ position: relative;
+ padding: 0.75em;
+ margin: 0.5em 0;
+ border-radius: 4px;
+ transition: background-color 0.2s;
+ display: flex;
+ align-items: center;
+}
+
+.radio-option:hover {
+ background-color: rgba(52, 152, 219, 0.1);
+}
+
+/* Custom radio button styling */
+input[type='radio'] {
+ margin-right: 0.75em;
+ width: 20px;
+ height: 20px;
+}
+
+input[type='radio']:focus-visible + label {
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+ border-radius: 2px;
+}
+
+input[type='radio'] + label {
+ cursor: pointer;
+ padding: 4px 8px;
+ border-radius: 4px;
+ transition: background-color 0.2s;
+ flex: 1;
+}
+
+/* Instructions section */
+.quiz-instructions {
+ background-color: #f8f9fa;
+ padding: 1em;
+ margin: 1em 0;
+ border-left: 4px solid var(--accent-color);
+ border-radius: 0 4px 4px 0;
+}
+
+/* Submit button */
+.form-controls {
+ margin-top: 2rem;
+ text-align: center;
+}
+
+.submit-button {
+ background-color: var(--accent-color);
+ color: white;
+ border: none;
+ padding: 12px 24px;
+ font-size: 1rem;
+ cursor: pointer;
+ border-radius: 4px;
+ transition: background-color 0.2s, transform 0.1s;
+ font-weight: 500;
+}
+
+.submit-button:hover {
+ background-color: #2980b9;
+}
+
+.submit-button:active {
+ transform: scale(0.98);
+}
+
+.submit-button:focus-visible {
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+}
+
+/* Results section */
+#results {
+ margin-top: 2rem;
+ padding: 1.5rem;
+ border-radius: 8px;
+ background-color: #f8fafc;
+ border: 1px solid var(--primary-color);
+}
+
+.feedback-details {
+ margin-top: 1rem;
+ padding: 1rem;
+ border-radius: 4px;
+}
+
+/* Utility classes */
+.visually-hidden {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+
+/* High contrast mode */
+@media (prefers-contrast: more) {
+ :root {
+ --primary-color: #000000;
+ --accent-color: #0000ee;
+ --focus-outline: 3px solid #000000;
+ }
+
+ header {
+ background: #ffffff;
+ border: 2px solid var(--primary-color);
+ }
+
+ nav a {
+ background-color: transparent;
+ border: 1px solid currentColor;
+ }
+
+ nav a:hover {
+ background-color: var(--primary-color);
+ }
+
+ .radio-option:hover {
+ background-color: #000000;
+ color: #ffffff;
+ }
+}
+
+/* Reduced motion */
+@media (prefers-reduced-motion: reduce) {
+ * {
+ transition-duration: 0.01ms !important;
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ scroll-behavior: auto !important;
+ }
+}
+
+/* Basic responsive design */
+@media (max-width: 600px) {
+ body {
+ padding: 10px;
+ }
+
+ fieldset {
+ padding: 0.5em;
+ }
+
+ header {
+ padding: 1.25rem;
+ }
+
+ nav ul {
+ gap: 0.75rem;
+ }
+}
+
+/* User Info Form */
+#user-info {
+ margin-bottom: 2rem;
+ padding: 1.5rem;
+ background-color: #f8fafc;
+ border-radius: 8px;
+ border: 1px solid #e2e8f0;
+}
+
+.form-control {
+ margin-bottom: 1.5rem;
+ position: relative;
+}
+
+.form-control label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+ color: var(--primary-color);
+}
+
+.form-control input {
+ width: 100%;
+ padding: 0.75rem;
+ font-size: 1rem;
+ border: 1px solid var(--primary-color);
+ border-radius: 4px;
+ transition: border-color 0.2s, box-shadow 0.2s;
+ box-sizing: border-box;
+}
+
+.form-control input:focus {
+ outline: none;
+ border-color: var(--accent-color);
+ box-shadow: 0 0 0 3px var(--focus-ring-color);
+}
+
+.form-control input[aria-invalid='true'] {
+ border-color: var(--error-color);
+}
+
+.form-control input[aria-invalid='true']:focus {
+ box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.25);
+}
+
+.error {
+ color: var(--error-color);
+ font-size: 0.875rem;
+ margin-top: 0.25rem;
+}
+
+.hint {
+ color: var(--secondary-color);
+ font-size: 0.875rem;
+ margin-top: 0.25rem;
+}
+
+/* Introduction section and images */
+#introduction {
+ padding: 2rem;
+ margin-bottom: 2rem;
+ background-color: #f8fafc;
+ border-radius: 12px;
+}
+
+#introduction h2 {
+ color: var(--primary-color);
+ font-size: 2rem;
+ margin-bottom: 1.5rem;
+}
+
+#introduction p {
+ max-width: 800px;
+ margin: 0 auto 2rem;
+}
+
+.hero-images {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 2rem;
+ margin: 2rem 0;
+}
+
+.decorative-image,
+.info-image {
+ max-width: 100%;
+ height: auto;
+ border-radius: 8px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+}
+
+.info-image {
+ padding: 1rem;
+ background: white;
+}
+
+@media (min-width: 768px) {
+ .hero-images {
+ flex-direction: row;
+ justify-content: center;
+ gap: 3rem;
+ }
+
+ .decorative-image,
+ .info-image {
+ width: 45%;
+ max-width: 400px;
+ }
+}
+
+/* Header and Navigation */
+header {
+ margin-bottom: 2rem;
+}
+
+h1,
+h2 {
+ margin-bottom: 1rem;
+}
+
+nav ul {
+ list-style: none;
+ padding: 0;
+ display: flex;
+ gap: 1rem;
+}
+
+nav a {
+ color: var(--accent-color);
+ text-decoration: none;
+}
+
+nav a:hover {
+ text-decoration: underline;
+}
+
+/* About page specific styles */
+#about {
+ padding: 3rem;
+ background-color: #f8fafc;
+ border-radius: 12px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+}
+
+#about h2 {
+ color: #2c3e50;
+ font-size: 2.5rem;
+ margin-bottom: 1.5rem;
+ border-bottom: 3px solid #3498db;
+ padding-bottom: 0.5rem;
+ display: inline-block;
+}
+
+#about p {
+ font-size: 1.2rem;
+ line-height: 1.8;
+ color: #34495e;
+ margin-bottom: 2rem;
+ max-width: 700px;
+}
+
+#about .hero-images {
+ margin: 3rem 0;
+ display: flex;
+ justify-content: center;
+}
+
+#about .hero-images img {
+ max-width: 100%;
+ height: auto;
+ border-radius: 12px;
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
+ transition: transform 0.3s ease;
+}
+
+#about .hero-images img:hover {
+ transform: scale(1.02);
+}
+
+/* Header improvements */
+#header {
+ padding: 2rem 0;
+ margin-bottom: 3rem;
+ border-bottom: 1px solid #eaeaea;
+}
+
+#header nav ul {
+ list-style: none;
+ padding: 0;
+ margin: 1rem 0;
+ display: flex;
+ gap: 2rem;
+}
+
+#header nav a {
+ color: #0040a3; /* Darker blue for better contrast */
+ text-decoration: none;
+ font-size: 1.1rem;
+ font-weight: 500;
+ padding: 0.5rem 1rem;
+ border-radius: 6px;
+ transition: all 0.2s ease;
+}
+
+#header nav a:hover {
+ background-color: #0040a3;
+ color: white;
+ text-decoration: none;
+}
+
+/* Responsive adjustments */
+@media (max-width: 600px) {
+ #about {
+ padding: 1.5rem;
+ }
+
+ #about h2 {
+ font-size: 2rem;
+ }
+
+ #about p {
+ font-size: 1.1rem;
+ }
+
+ #header nav ul {
+ gap: 1rem;
+ }
+}
+/* Removed invalid JSX code */
\ No newline at end of file
diff --git a/frontend/components/App.jsx b/frontend/components/App.jsx
new file mode 100644
index 00000000..1c6737aa
--- /dev/null
+++ b/frontend/components/App.jsx
@@ -0,0 +1,53 @@
+
+import React from "react"
+import Card from "./components/card"
+import { createGlobalStyle } from "styled-components";
+import "./App.css"
+import card from " ./data/card/json";
+import styled from 'styled-components';
+import styled, { css } from 'styled-components'
+
+const CardWrapper = styled.article``;
+
+const Button = styled.button`
+ background: transparent;
+ border-radius: 3px;
+ border: 2px solid #BF4F74;
+ color: '#BF4F74';
+ margin: 0 1em;
+ padding: 0.25em 1em;
+
+
+ ${props =>
+ props.$primary &&
+ css`
+ background: '#BF4F74';
+ color: white;
+ `};
+`
+// Here we're saying that when the $primary property is set we want to add some more css to our component, in this case change the background and
+console.log(card)
+
+// Removed duplicate Button declaration
+
+const App = () => {
+ return (
+ <>
+
Vite project
+
+
+
+ >
+ )
+}
+
+export default App
\ No newline at end of file
diff --git a/frontend/components/GlobalStyle.jsx b/frontend/components/GlobalStyle.jsx
new file mode 100644
index 00000000..4bf9c0d6
--- /dev/null
+++ b/frontend/components/GlobalStyle.jsx
@@ -0,0 +1,8 @@
+import { createGlobalStyle } from "styled-components";
+export const GlobalStyle = createGlobalStyle`
+*{
+box-sizing: border-box;
+margin: 0;
+padding: 0;
+}
+`
\ No newline at end of file
diff --git a/frontend/components/Home.jsx b/frontend/components/Home.jsx
new file mode 100644
index 00000000..0e555f46
--- /dev/null
+++ b/frontend/components/Home.jsx
@@ -0,0 +1,6 @@
+import {appContentStore} from "../stores/appContentStore"
+export const Home () => {
+ const { appContent } = appContentStore()
+ return(
+ {appContent.heading}
+}
\ No newline at end of file
diff --git a/frontend/components/LoginForm.jsx b/frontend/components/LoginForm.jsx
new file mode 100644
index 00000000..a406baa0
--- /dev/null
+++ b/frontend/components/LoginForm.jsx
@@ -0,0 +1,61 @@
+import { useState } from "react";
+
+const LoginForm = () => {
+ const [formData, setFormData] = useState({
+ email: "",
+ password: "",
+ });
+
+ const [error, setError] = useState("");
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+
+ if (!formData.email || !formData.password) {
+ setError("Please fill in both fields");
+ return;
+ }
+
+ setError("");
+
+ fetch("http://localhost:8080/users/login", {
+ method: "POST",
+ body: JSON.stringify({ email: formData.email, password: formData.password }),
+ headers: {
+ "Content-Type": "application/json"
+ }
+ })
+ .then(() => {
+ // Reset form
+ e.target.reset()
+ })
+ .catch(error => {
+ console.log(error)
+ })
+
+ };
+
+ return (
+
+ );
+};
+
+export default LoginForm;
\ No newline at end of file
diff --git a/frontend/components/SignupForm.jsx b/frontend/components/SignupForm.jsx
new file mode 100644
index 00000000..8be5785b
--- /dev/null
+++ b/frontend/components/SignupForm.jsx
@@ -0,0 +1,52 @@
+import { useState } from "react";
+
+const SignupForm = () => {
+ const [formData, setFormData] = useState({
+ email: "",
+ password: "",
+ });
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ console.log(formData);
+
+ fetch("http://localhost:8080/users", {
+ method: "POST",
+ body: JSON.stringify({ email: formData.email, password: formData.password }),
+ headers: {
+ "Content-Type": "application/json"
+ }
+ })
+ .then(() => {
+ // Reset form
+ e.target.reset()
+ })
+ .catch(error => {
+ console.log(error)
+ })
+
+ };
+
+ return (
+
+ );
+};
+
+export default SignupForm;
\ No newline at end of file
diff --git a/frontend/components/breakpoints.js b/frontend/components/breakpoints.js
new file mode 100644
index 00000000..2b9e50e6
--- /dev/null
+++ b/frontend/components/breakpoints.js
@@ -0,0 +1,17 @@
+import { media } from "..styles/media"
+// Example usage of media queries with styled-components
+import styled from 'styled-components';
+
+const StyledComponent = styled.div`
+ @media ${media.desktop} {
+ width: 250px;
+ }
+`;
+export const media = {
+ mobile: '(max-width: 768px)',
+ tablet: '(max-width: 1024px)',
+ desktop: '(min-width: 1025px)'
+
+
+
+}
\ No newline at end of file
diff --git a/frontend/components/card.css b/frontend/components/card.css
new file mode 100644
index 00000000..11fb9b07
--- /dev/null
+++ b/frontend/components/card.css
@@ -0,0 +1,8 @@
+@import "tailwindcss";
+card.css
+article {
+ border: 2px solid blue;
+ padding: 1rem;
+ width: 400px;
+
+}
\ No newline at end of file
diff --git a/frontend/components/card.jsx b/frontend/components/card.jsx
new file mode 100644
index 00000000..1c09f750
--- /dev/null
+++ b/frontend/components/card.jsx
@@ -0,0 +1,21 @@
+import "./card.css"
+import styled from "styled-components"
+
+const CardWrapper = styled.article`
+ border: 2px solid blue;
+ padding: 1rem;
+ width: 400px;
+`;
+
+
+const Card =({ title, text }) => {
+ return (
+
+
+ {title}
+ {text}
+
+
+ );
+}
+export default Card;
\ No newline at end of file
diff --git a/frontend/components/header.jsx b/frontend/components/header.jsx
new file mode 100644
index 00000000..cb563d70
--- /dev/null
+++ b/frontend/components/header.jsx
@@ -0,0 +1,13 @@
+const header = () => {
+ return (
+
+ )
+}
+export default header
\ No newline at end of file
diff --git a/frontend/components/main.jsx b/frontend/components/main.jsx
new file mode 100644
index 00000000..42e74107
--- /dev/null
+++ b/frontend/components/main.jsx
@@ -0,0 +1,10 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+
+import App from '/App.jsx'
+
+createRoot(document.getElementById('root')).render(
+
+
+
+)
\ No newline at end of file
diff --git a/frontend/components/pages/UserSettings.jsx b/frontend/components/pages/UserSettings.jsx
new file mode 100644
index 00000000..ef7fc4fc
--- /dev/null
+++ b/frontend/components/pages/UserSettings.jsx
@@ -0,0 +1,17 @@
+import { useUserStore } from "../stores/userstore"
+export const UserSettings = () => {
+ const { toggleLogin, } inCrementAge, setUserName} isLoggedIn, userName } = useUserStore()
+ return(
+
+
User Settings
+
Logged in: {isLoggedIn ? "Yes" : "No"}
+
Toggle Login
+
Increment Age
+
+ New User Name:
+ setUserName(event.target.value)}/>
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/frontend/components/pages/Userinfo.jsx b/frontend/components/pages/Userinfo.jsx
new file mode 100644
index 00000000..19415b8c
--- /dev/null
+++ b/frontend/components/pages/Userinfo.jsx
@@ -0,0 +1,11 @@
+import { useUserStore } from "../stores/userStore"
+export const UserInfo = () => {
+ const { userName, age } = useUserStore()
+
+return (
+
+}
User Profile
+
User Name: {userName}>
+
Age: {age}
+
+))
\ No newline at end of file
diff --git a/frontend/components/pages/stores/appContentStore.jsx b/frontend/components/pages/stores/appContentStore.jsx
new file mode 100644
index 00000000..99d183c3
--- /dev/null
+++ b/frontend/components/pages/stores/appContentStore.jsx
@@ -0,0 +1,5 @@
+import {create} from "zustand"
+export const appContentStore = create(() => ({}))
+appContent:{
+ heading: "State-Management-Zustand-js-project-portfolio-Code-lab-web-app-"
+}
\ No newline at end of file
diff --git a/frontend/components/pages/stores/userStore.jsx b/frontend/components/pages/stores/userStore.jsx
new file mode 100644
index 00000000..67e4a179
--- /dev/null
+++ b/frontend/components/pages/stores/userStore.jsx
@@ -0,0 +1,9 @@
+import { create } from "zustand"
+export const useUserStore = create ((set) =>({
+ isLoggedIn: false,
+ age: 25,
+ userName: "John Doe",
+ toggleLogin: () set ((state) => ({isLoggedIn:})) !state.isLoggedIn}))
+ incrementAge: () => set ((state) => ({age: state.age +1})),
+ setUserName: (newUserName) => set ({userName:})
+})
\ No newline at end of file
diff --git a/frontend/components/theme.js b/frontend/components/theme.js
new file mode 100644
index 00000000..22f4a8d8
--- /dev/null
+++ b/frontend/components/theme.js
@@ -0,0 +1,22 @@
+padding: ${props.theme.spacing.medium};
+import {
+ ThemeProvider } from "styled-components"
+const App = () =>
+ return{
+
+
+
+
+ )
+ }
+export const theme = {
+ spacing: {
+ small: '0.5rem',
+ medium: '1rem',
+ large: '2rem'
+ },
+ colours:{
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/frontend/components/useDarkMode.jsx b/frontend/components/useDarkMode.jsx
new file mode 100644
index 00000000..041e6d23
--- /dev/null
+++ b/frontend/components/useDarkMode.jsx
@@ -0,0 +1,14 @@
+};
+const use DarkMode =() => {
+ const [enabled, setEnabled]=useLocalStorage('dark-theme');
+ const isEnabled = typeof enabledState ===
+ 'undefined' && enabled;
+ useEffect(()) => }
+ const className = 'dark';
+ const bodyClass = window.document.body.classList;
+ isEnabled ? bodyclass.add(className):bodyclass.remove(className);
+},[enabled, isEnabled]);
+return [enabled, setEnabled]
+};
+export default useDarkMode;
+}
\ No newline at end of file
diff --git a/frontend/public/#peace.jpg b/frontend/public/#peace.jpg
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/App.css b/frontend/public/App.css
new file mode 100644
index 00000000..092764ef
--- /dev/null
+++ b/frontend/public/App.css
@@ -0,0 +1,640 @@
+* Base styles with accessibility considerations */
+:root {
+ --primary-color: #2c3e50;
+ --background-color: #ffffff;
+ --accent-color: #0040a3; /* Darker blue for better contrast */
+ --error-color: #e74c3c;
+ --success-color: #27ae60;
+ --focus-outline: 3px solid var(--accent-color);
+ --focus-ring-color: rgba(0, 86, 179, 0.5);
+ --progress-bg: #edf2f7;
+ --modal-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
+}
+
+/* Apply box-sizing border-box to all elements */
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+/* Modal Dialog */
+.modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.6);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+ backdrop-filter: blur(4px);
+}
+
+/* Ensure hidden attribute works properly */
+.modal[hidden] {
+ display: none;
+}
+
+.modal-content {
+ background-color: var(--background-color);
+ padding: 2rem;
+ border-radius: 8px;
+ max-width: 500px;
+ width: 90%;
+ max-height: 90vh;
+ overflow-y: auto;
+ box-shadow: var(--modal-shadow);
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ animation: modalAppear 0.3s ease-out;
+}
+
+@keyframes modalAppear {
+ from {
+ opacity: 0;
+ transform: translateY(-20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+/* Checkbox styling */
+.checkbox-container {
+ display: flex;
+ align-items: center;
+ margin-bottom: 0.5rem;
+}
+
+.checkbox-container input[type='checkbox'] {
+ width: auto;
+ margin-right: 0.5rem;
+}
+
+select {
+ width: 100%;
+ padding: 0.5rem;
+ font-size: 1rem;
+ border: 1px solid var(--secondary-color);
+ border-radius: 4px;
+}
+
+.checkbox-container label {
+ margin-bottom: 0;
+}
+.modal-body {
+ margin: 1.5rem 0;
+}
+
+.intro-section {
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.modal-footer {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 2rem;
+ gap: 1rem;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+ padding-top: 1.5rem;
+}
+
+#modal-title {
+ color: var(--primary-color);
+ margin: 0 0 1rem 0;
+ font-size: 1.5rem;
+ font-weight: 600;
+}
+
+.modal button {
+ padding: 0.75rem 1.5rem;
+ border-radius: 6px;
+ font-size: 1rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+#save-settings {
+ background-color: var(--accent-color);
+ color: white;
+ border: none;
+}
+
+#save-settings:hover {
+ background-color: #004494;
+}
+
+#close-modal {
+ background-color: transparent;
+ border: 1px solid var(--primary-color);
+ color: var(--primary-color);
+}
+
+#close-modal:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+
+/* Base styles for readability */
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial,
+ sans-serif;
+ line-height: 1.6;
+ color: var(--primary-color);
+ background-color: var(--background-color);
+ margin: 0;
+ padding: 20px;
+ font-size: 16px;
+ max-width: 800px;
+ margin: 0 auto;
+}
+
+/* Skip link with enhanced visibility */
+.skip-link {
+ position: absolute;
+ top: -40px;
+ left: 0;
+ background: var(--accent-color);
+ color: white;
+ padding: 8px;
+ z-index: 100;
+ transition: top 0.3s;
+}
+
+.skip-link:focus {
+ top: 0;
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+}
+
+/* Enhanced focus styles */
+:focus-visible {
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+ border-radius: 2px;
+}
+
+/* Progress bar styles */
+.quiz-progress {
+ margin: 2rem 0;
+}
+/* Images */
+.decorative-image,
+.info-image {
+ max-width: 15rem;
+ height: auto;
+ margin: 1rem 0;
+ border-radius: 4px;
+}
+
+.progress-bar {
+ background-color: var(--progress-bg);
+ border-radius: 8px;
+ height: 20px;
+ overflow: hidden;
+ position: relative;
+}
+
+.progress-fill {
+ background-color: var(--accent-color);
+ height: 100%;
+ transition: width 0.3s ease;
+ border-radius: 8px;
+}
+
+.progress-text {
+ margin-top: 0.5rem;
+ text-align: center;
+ font-weight: 500;
+}
+
+/* Question groups */
+.question-group {
+ margin-bottom: 2rem;
+ padding: 1rem;
+ border: 1px solid #e2e8f0;
+ border-radius: 8px;
+ background-color: #f8fafc;
+}
+
+.question-heading {
+ color: var(--primary-color);
+ margin-bottom: 1rem;
+ font-size: 1.1rem;
+}
+
+/* Form elements */
+fieldset {
+ border: 1px solid var(--primary-color);
+ margin: 1em 0;
+ padding: 1em;
+ border-radius: 4px;
+}
+
+legend {
+ font-weight: bold;
+ padding: 0.5em 1em;
+ color: var(--primary-color);
+ background-color: #f8fafc;
+ border: 1px solid var(--primary-color);
+ border-radius: 4px;
+}
+
+.radio-group {
+ margin: 1em 0;
+}
+
+/* Enhanced radio button styling */
+.radio-option {
+ position: relative;
+ padding: 0.75em;
+ margin: 0.5em 0;
+ border-radius: 4px;
+ transition: background-color 0.2s;
+ display: flex;
+ align-items: center;
+}
+
+.radio-option:hover {
+ background-color: rgba(52, 152, 219, 0.1);
+}
+
+/* Custom radio button styling */
+input[type='radio'] {
+ margin-right: 0.75em;
+ width: 20px;
+ height: 20px;
+}
+
+input[type='radio']:focus-visible + label {
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+ border-radius: 2px;
+}
+
+input[type='radio'] + label {
+ cursor: pointer;
+ padding: 4px 8px;
+ border-radius: 4px;
+ transition: background-color 0.2s;
+ flex: 1;
+}
+
+/* Instructions section */
+.quiz-instructions {
+ background-color: #f8f9fa;
+ padding: 1em;
+ margin: 1em 0;
+ border-left: 4px solid var(--accent-color);
+ border-radius: 0 4px 4px 0;
+}
+
+/* Submit button */
+.form-controls {
+ margin-top: 2rem;
+ text-align: center;
+}
+
+.submit-button {
+ background-color: var(--accent-color);
+ color: white;
+ border: none;
+ padding: 12px 24px;
+ font-size: 1rem;
+ cursor: pointer;
+ border-radius: 4px;
+ transition: background-color 0.2s, transform 0.1s;
+ font-weight: 500;
+}
+
+.submit-button:hover {
+ background-color: #2980b9;
+}
+
+.submit-button:active {
+ transform: scale(0.98);
+}
+
+.submit-button:focus-visible {
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+}
+
+/* Results section */
+#results {
+ margin-top: 2rem;
+ padding: 1.5rem;
+ border-radius: 8px;
+ background-color: #f8fafc;
+ border: 1px solid var(--primary-color);
+}
+
+.feedback-details {
+ margin-top: 1rem;
+ padding: 1rem;
+ border-radius: 4px;
+}
+
+/* Utility classes */
+.visually-hidden {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+
+/* High contrast mode */
+@media (prefers-contrast: more) {
+ :root {
+ --primary-color: #000000;
+ --accent-color: #0000ee;
+ --focus-outline: 3px solid #000000;
+ }
+
+ header {
+ background: #ffffff;
+ border: 2px solid var(--primary-color);
+ }
+
+ nav a {
+ background-color: transparent;
+ border: 1px solid currentColor;
+ }
+
+ nav a:hover {
+ background-color: var(--primary-color);
+ }
+
+ .radio-option:hover {
+ background-color: #000000;
+ color: #ffffff;
+ }
+}
+
+/* Reduced motion */
+@media (prefers-reduced-motion: reduce) {
+ * {
+ transition-duration: 0.01ms !important;
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ scroll-behavior: auto !important;
+ }
+}
+
+/* Basic responsive design */
+@media (max-width: 600px) {
+ body {
+ padding: 10px;
+ }
+
+ fieldset {
+ padding: 0.5em;
+ }
+
+ header {
+ padding: 1.25rem;
+ }
+
+ nav ul {
+ gap: 0.75rem;
+ }
+}
+
+/* User Info Form */
+#user-info {
+ margin-bottom: 2rem;
+ padding: 1.5rem;
+ background-color: #f8fafc;
+ border-radius: 8px;
+ border: 1px solid #e2e8f0;
+}
+
+.form-control {
+ margin-bottom: 1.5rem;
+ position: relative;
+}
+
+.form-control label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+ color: var(--primary-color);
+}
+
+.form-control input {
+ width: 100%;
+ padding: 0.75rem;
+ font-size: 1rem;
+ border: 1px solid var(--primary-color);
+ border-radius: 4px;
+ transition: border-color 0.2s, box-shadow 0.2s;
+ box-sizing: border-box;
+}
+
+.form-control input:focus {
+ outline: none;
+ border-color: var(--accent-color);
+ box-shadow: 0 0 0 3px var(--focus-ring-color);
+}
+
+.form-control input[aria-invalid='true'] {
+ border-color: var(--error-color);
+}
+
+.form-control input[aria-invalid='true']:focus {
+ box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.25);
+}
+
+.error {
+ color: var(--error-color);
+ font-size: 0.875rem;
+ margin-top: 0.25rem;
+}
+
+.hint {
+ color: var(--secondary-color);
+ font-size: 0.875rem;
+ margin-top: 0.25rem;
+}
+
+/* Introduction section and images */
+#introduction {
+ padding: 2rem;
+ margin-bottom: 2rem;
+ background-color: #f8fafc;
+ border-radius: 12px;
+}
+
+#introduction h2 {
+ color: var(--primary-color);
+ font-size: 2rem;
+ margin-bottom: 1.5rem;
+}
+
+#introduction p {
+ max-width: 800px;
+ margin: 0 auto 2rem;
+}
+
+.hero-images {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 2rem;
+ margin: 2rem 0;
+}
+
+.decorative-image,
+.info-image {
+ max-width: 100%;
+ height: auto;
+ border-radius: 8px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+}
+
+.info-image {
+ padding: 1rem;
+ background: white;
+}
+
+@media (min-width: 768px) {
+ .hero-images {
+ flex-direction: row;
+ justify-content: center;
+ gap: 3rem;
+ }
+
+ .decorative-image,
+ .info-image {
+ width: 45%;
+ max-width: 400px;
+ }
+}
+
+/* Header and Navigation */
+header {
+ margin-bottom: 2rem;
+}
+
+h1,
+h2 {
+ margin-bottom: 1rem;
+}
+
+nav ul {
+ list-style: none;
+ padding: 0;
+ display: flex;
+ gap: 1rem;
+}
+
+nav a {
+ color: var(--accent-color);
+ text-decoration: none;
+}
+
+nav a:hover {
+ text-decoration: underline;
+}
+
+/* About page specific styles */
+#about {
+ padding: 3rem;
+ background-color: #f8fafc;
+ border-radius: 12px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+}
+
+#about h2 {
+ color: #2c3e50;
+ font-size: 2.5rem;
+ margin-bottom: 1.5rem;
+ border-bottom: 3px solid #3498db;
+ padding-bottom: 0.5rem;
+ display: inline-block;
+}
+
+#about p {
+ font-size: 1.2rem;
+ line-height: 1.8;
+ color: #34495e;
+ margin-bottom: 2rem;
+ max-width: 700px;
+}
+
+#about .hero-images {
+ margin: 3rem 0;
+ display: flex;
+ justify-content: center;
+}
+
+#about .hero-images img {
+ max-width: 100%;
+ height: auto;
+ border-radius: 12px;
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
+ transition: transform 0.3s ease;
+}
+
+#about .hero-images img:hover {
+ transform: scale(1.02);
+}
+
+/* Header improvements */
+#header {
+ padding: 2rem 0;
+ margin-bottom: 3rem;
+ border-bottom: 1px solid #eaeaea;
+}
+
+#header nav ul {
+ list-style: none;
+ padding: 0;
+ margin: 1rem 0;
+ display: flex;
+ gap: 2rem;
+}
+
+#header nav a {
+ color: #0040a3; /* Darker blue for better contrast */
+ text-decoration: none;
+ font-size: 1.1rem;
+ font-weight: 500;
+ padding: 0.5rem 1rem;
+ border-radius: 6px;
+ transition: all 0.2s ease;
+}
+
+#header nav a:hover {
+ background-color: #0040a3;
+ color: white;
+ text-decoration: none;
+}
+
+/* Responsive adjustments */
+@media (max-width: 600px) {
+ #about {
+ padding: 1.5rem;
+ }
+
+ #about h2 {
+ font-size: 2rem;
+ }
+
+ #about p {
+ font-size: 1.1rem;
+ }
+
+ #header nav ul {
+ gap: 1rem;
+ }
+}
diff --git a/frontend/public/ReactHook.js b/frontend/public/ReactHook.js
new file mode 100644
index 00000000..c67fc69d
--- /dev/null
+++ b/frontend/public/ReactHook.js
@@ -0,0 +1,226 @@
+import React from 'react';
+
+// Function component using function keyword
+function FunctionComponent(props) {
+ return (
+
+
Hello, {props.name}!
+
This is a function component.
+
+ );
+}
+
+// Function component using arrow function syntax
+const FunctionComponent = (props) => {
+ return (
+
+
Hello, {props.name}!
+
This is a function component.
+
+ );
+};
+
+// Removed redundant default export
+import React, { useState } from 'react';
+
+const FunctionComponent = () => {
+ // Using useState Hook to manage state
+ const [count, setCount] = useState(0);
+
+ return (
+
+
Count: {count}
+
setCount(count + 1)}>Increment
+
+ );
+};
+
+// Removed redundant default export
+import React, { useState, useEffect } from 'react';
+
+const FunctionComponent = () => {
+ const [count, setCount] = useState(0);
+
+ // useEffect Hook to replicate componentDidMount and componentDidUpdate
+ useEffect(() => {
+ // This code block runs after every render
+ console.log("Component did mount or update");
+
+ // Clean-up function (replicating componentWillUnmount)
+ return () => {
+ console.log("Component will unmount");
+ };
+ });
+
+ return (
+
+
Count: {count}
+
setCount(count + 1)}>Increment
+
+ );
+};
+
+export { FunctionComponent };
+import React, { Component } from 'react';
+
+// Define a class component that extends React.Component or React.PureComponent
+class ClassComponent extends Component {
+ // Define constructor if necessary
+ constructor(props) {
+ super(props);
+ // Initialize state if needed
+ this.state = {
+ count: 0
+ };
+ }
+
+ // Define lifecycle methods if necessary
+ componentDidMount() {
+ // Code to run after the component is mounted
+ }
+
+ // Define instance methods if necessary
+ handleClick = () => {
+ // Update state or perform other logic
+ this.setState({ count: this.state.count + 1 });
+ }
+
+ // Define render() method to return JSX
+ render() {
+ return (
+
+
Count: {this.state.count}
+
Increment
+
+ );
+ }
+}
+
+// Removed redundant default export
+import React, { Component } from 'react';
+
+class ClassComponent extends Component {
+ constructor(props) {
+ super(props);
+ // Initialize state
+ this.state = {
+ count: 0
+ };
+ }
+
+ // Define a method to update state
+ incrementCount = () => {
+ // Use this.setState() to update state
+ this.setState({ count: this.state.count + 1 });
+ }
+
+ render() {
+ return (
+
+
Count: {this.state.count}
+
Increment
+
+ );
+ }
+}
+
+export { ClassComponent };
+import React, { Component } from 'react';
+
+class ClassComponent extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ data: null
+ };
+ }
+
+ componentDidMount() {
+ // Fetch initial data when the component mounts
+ this.fetchData();
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ // Check if the data has changed
+ if (prevState.data !== this.state.data) {
+ // Data has changed, perform additional actions
+ console.log('Data has been updated:', this.state.data);
+ }
+ }
+
+ componentWillUnmount() {
+ // Cleanup tasks before the component is unmounted
+ console.log('Component will unmount');
+ // For example, remove event listeners, cancel ongoing tasks, etc.
+ }
+
+ fetchData() {
+ // Simulate fetching data from an API
+ setTimeout(() => {
+ this.setState({ data: 'Some data fetched from API' });
+ }, 1000);
+ }
+
+ render() {
+ return (
+
+
Data: {this.state.data}
+
+ );
+ }
+}
+
+import React, { Component } from 'react';
+
+class ClassComponent extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ count: 0
+ };
+ }
+
+ // Custom method to handle incrementing count
+ handleIncrement = () => {
+ this.setState({ count: this.state.count + 1 });
+ }
+
+ // Custom method to handle decrementing count
+ handleDecrement = () => {
+ this.setState({ count: this.state.count - 1 });
+ }
+
+ render() {
+ return (
+
+
Count: {this.state.count}
+
Increment
+
Decrement
+
+ );
+ }
+}
+
+export { ClassComponent };
+import React, { useState } from 'react';
+
+function Counter() {
+ const [count, setCount] = useState(0);
+
+ return (
+
+
Count: {count}
+
setCount(count + 1)}>Increment
+
+ );
+}
+import { useTheme } from 'styled-components'
+
+
+const MyComponent = () => {
+ const theme = useTheme()
+
+
+ console.log('Current theme: ', theme)
+ // ...
+}
\ No newline at end of file
diff --git a/frontend/public/about.html b/frontend/public/about.html
new file mode 100644
index 00000000..38a11eb8
--- /dev/null
+++ b/frontend/public/about.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+ About Us
+
+
+
+ Skip to main content
+
+
+
+ About Our Website Feedback Initiative
+
+ We are committed to making our website accessible to everyone. Your feedback helps us improve and create a better experience for all users.
+
+
+
+
+
+
Accessibility Features
+
+
+
+ Screen Reader Compatibility
+
+
+
+
+
Our website is fully compatible with screen readers.
+
+
+
+
+
+ Keyboard Navigation
+
+
+
+
+
All interactive elements are accessible via keyboard navigation. You can use the Tab key to move between links and Shift + Tab to move back.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/public/accordion.js b/frontend/public/accordion.js
new file mode 100644
index 00000000..273570d1
--- /dev/null
+++ b/frontend/public/accordion.js
@@ -0,0 +1,66 @@
+function initAccordion(){
+ const accordion = document.querySelector('accordion');
+ if (!accordion) return;
+
+ const buttons = accordion.querySelectorAll('accordion-button');
+
+ buttons.forEach((button, index) => {
+ button.addEventListener('keydown', (event) => {
+ const targetId = button.getAttribute('aria-controls');
+ const targetPanel = document.getElementById(targetId);
+
+ switch (event.key){
+ case 'ArrowDown':
+ case 'ArrowRight':
+ event.preventDefault();
+ const nextButton = buttons[(index + 1) % buttons.length];
+ nextButton.focus();
+ break;
+ case 'ArrowUp':
+ case 'ArrowLeft':
+ event.preventDefault();
+ case 'ArrowUp':
+ case 'ArrowLeft':
+ event.preventDefault();
+ const prevButton = buttons[(index - 1 + buttons.length) % buttons.length];
+ prevButton.focus();
+ break;
+ case 'Home':
+ event.preventDefault();
+ buttons[0].focus();
+ break;
+ case 'End':
+ event.preventDefault();
+ buttons[buttons.length - 1].focus();
+ break;
+ case ' ':
+ case 'Enter':
+ event.preventDefault();
+ togglePanel(button, targetPanel);
+ break;
+ }
+});
+button.addEventListener('click', () =>{
+ const targetId = button .getAttribute('aria-controls');
+ const targetPanel = document.getElementById(targetId);
+});
+});
+
+function togglePanel(button, panel) {
+const isExpanded = button.getAttribute('aria-expanded') === 'true';
+const newExpandedState = !isExpanded;
+button.setAttribute('aria-expanded', newExpandedState);
+if (newExpandedState) {
+ panel.hidden =false;
+ requestAnimationFrame(() => {
+ panel.style.maxHeight = panel.scrollHeight + 'px';
+ });
+} else {
+ panel.addEventListener('transitionend', () => {
+ panel.hidden = true;
+ }, { once: true });
+ }
+}
+
+document.addEventListener('DOMContentLoaded', initAccordion);
+}
diff --git a/frontend/public/backend/server.js b/frontend/public/backend/server.js
new file mode 100644
index 00000000..484619a9
--- /dev/null
+++ b/frontend/public/backend/server.js
@@ -0,0 +1,136 @@
+import express from 'express'
+import bodyParser from 'body-parser'
+import cors from 'cors'
+import crypto from 'crypto'
+import mongoose from 'mongoose'
+import bcrypt from 'bcrypt-nodejs'
+
+const mongoUrl =process.env_MONGO_URL II "mongodb://localhost/auth"
+mongoose.connect(mongoUrl, { useNewUrlParser: true, useundefinedtopology: true})
+mongoose.Promise = Promise
+
+const { Schema, model } = mongoose
+const userSchema = new Schema({
+
+const User = mongoose.model('User', {
+ name: {
+ type: String,
+ unique: true
+ },
+ password:{
+ type:String,
+ required:true
+ },
+ accessToken:{
+ type:String,
+ default: () => crypto.randomBytes(128)toString('hex')
+ }
+ });
+ const User = model("User", userSchema)
+
+ // Example
+ // POST Request
+ const request = {name: "Bob", password: "foobar};
+ // DB Entry
+ const dbEntry = {name :"Bob, password:"5abbc32983def"}
+ bcrypt.compareSync(request.password, dbEntry.password);
+ // One-way encryption
+const user = new User({name:"Bob", password:bcrypt.hashSync("foobar")});
+user.save();
+// Defines the port the app will run on. Defaults to 8080, but can be overritten when starting the server. For example:
+//
+// PORT-9000 npm start
+const port = process.env.PORT II 8080
+const app = express()
+const authenticateUser = async (req, res, next) => {
+ const user = await User.findOne({accesToken: req.header('Authorization')});
+ if(user){
+ req.user = user;
+ next();
+ {else{
+res.status(401).json({loggedOut:true});
+ }}
+ }
+}
+
+// Add middlewares to enable cors and json body parsing
+app.use(cors())
+app.use(express.json());
+app.use(bodyParser.json())
+
+// Start defining your routes here
+app.get('/', (req, res) => {
+ res.send('Hello Member')
+ app.post('/tweets' authenticateUser);
+ app.post('/tweets', async (req,res) =>{
+ // This will only happen if the next() function is called from middleware!
+ // now we can access the req.user object from the middleware
+ })
+
+ }
+ })
+})
+
+// Start defining your routes here
+app.get('/,(req, res) => {
+ res.send('Hello world')
+})
+app.post('/sessions' async (req res) => {
+ const user = await User.findOne({name: req.body.name});
+ if(user && bcrypt.compareSync(req.body.password, user.password)){
+ // Success
+ res.json({userId: user._id, accessToken}};
+ }else{
+ // Failure
+ // a.User does not exist
+ // b. Encrypted password does not march
+ res.json({notFound: true});
+ }
+ }
+});
+app.post("/users", (req, res) => {
+ try {
+ const { name, email, password } = req.body
+ const salt = bcrypt.genSaltSync()
+ const user = new User({ name, email, password: bcrypt.hashSync(password, salt) })
+ user.save()
+ res.status(201).json({
+ success: true,
+ message: "User created",
+ id: user._id,
+ accessToken: user.accessToken,
+ })
+ } catch (error) {
+ res.status(400).json({
+ success: false,
+ message: "Could not create user",
+ errors: error
+ })
+ }
+ })
+
+ app.get("/secrets", authenticateUser)
+app.get("/secrets", (req, res) => {
+ res.json({
+ secret: "This is secret"
+ app.get('/secrets', (req, res) =>{
+ res.jsons({secret: 'This is a super secret message'})
+ });
+ }
+ app.post('/sessions' async (req, res) => {
+ const user = await User.findOne({email: req.body.email});
+ if (user && bcrypt.compareSync(req.body.password. user.password)){
+ res.json({userId: user_Id, assessToken: user.accessToken});
+ }else{
+ res.json({notFound: true});
+
+
+
+
+// Start the server
+})
+app.listen(port, () => {
+ console.log('Server running on http://localhost:${port}')
+})
+ console.log(bcrypt.hashSync("foobar"));
+})
\ No newline at end of file
diff --git a/frontend/public/backend/settings.json b/frontend/public/backend/settings.json
new file mode 100644
index 00000000..03adc8d2
--- /dev/null
+++ b/frontend/public/backend/settings.json
@@ -0,0 +1,4 @@
+{
+ "IDX.aI.enableInlineCompletion": true,
+ "IDX.aI.enableCodebaseIndexing": true
+}
\ No newline at end of file
diff --git a/frontend/public/index.html b/frontend/public/index.html
new file mode 100644
index 00000000..86d6cc3f
--- /dev/null
+++ b/frontend/public/index.html
@@ -0,0 +1,115 @@
+
+
+
+
+
+ Website Feedback
+
+
+
+ Skip to main content
+
+
+
+
+ Introduction
+ We value your feedback! Help us improve our website by sharing your experience.
+
+ Continue
+
+
+
+
+
+
+ Thank you for your feedback!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/public/johanska b/frontend/public/johanska
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/keyboardnavigation.js b/frontend/public/keyboardnavigation.js
new file mode 100644
index 00000000..ba6123a7
--- /dev/null
+++ b/frontend/public/keyboardnavigation.js
@@ -0,0 +1,41 @@
+// JavaScript for keyboard navigation
+Element.addEventListener('keydown', (e) => {
+ switch (e.key) {
+ case 'Enter':
+ case ' ':
+ // Activate the element
+ break;
+ case 'ArrowRight':
+ case 'ArrowDown':
+ // Move to next item
+ break;
+ case 'ArrowLeft':
+ case 'ArrowUp':
+ // Move to previous item
+ break;
+ case 'Home':
+ // Move to first item
+ break;
+ case 'End':
+ // Move to last item
+ break;
+ }
+});
+
+// Focus Management
+
+// After form submission
+submitButton.addEventListener('click', () => {
+ // Hide form
+ FormData.hidden = true;
+
+ // Show results
+ SpeechRecognitionResultList.hidden = false;
+
+ // Set focus to results
+ SpeechRecognitionResultList.setAttribute('tabindex', '-1');
+ SpeechRecognitionResultList.focus();
+
+ // Announce to screen readers
+ announcer.textContent = 'Form submitted successfully';
+});
\ No newline at end of file
diff --git a/frontend/public/main.js b/frontend/public/main.js
new file mode 100644
index 00000000..c54336a3
--- /dev/null
+++ b/frontend/public/main.js
@@ -0,0 +1,156 @@
+document.addEventListener('DOMContentLoaded', () => {
+ const introSection = document.getElementById('user-info');
+ const announcer = document.getElementById('announcer');
+
+ const introContinueButton = document.getElementById('intro-continue');
+
+introContinueButton.addEventListener('click', () => {
+ introSection.hidden = true;
+ const userSection = document.getElementById('user-info-section');
+ userSection.hidden = false;
+ window.location.hash = '#user-info';
+ document.getElementById('name').focus();
+ announcer.textContent = 'Moved to user information section';
+ });
+});
+
+const userInfoForm = document.getElementById('user-info-form');
+const nameInput = document.getElementById('name');
+const emailInput = document.getElementById('email');
+const emailError = document.getElementById('email-error');
+const nameError = document.getElementById('name-error');
+let userName = '';
+
+function clearError(input, errorElement) {
+ input.removeAttribute('aria-invalid');
+ errorElement.textContent = '';
+ errorElement.hidden = true;
+}
+
+function isValidEmail(email) {
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
+}
+
+function showError(input, errorElement, message) {
+ input.setAttribute('aria-invalid', 'true');
+ errorElement.textContent = message;
+ errorElement.hidden = false;
+}
+
+nameInput.addEventListener('input', () => {
+ if (nameInput.value.trim()) {
+ clearError(nameInput, nameError);
+ }
+});
+
+emailInput.addEventListener('input', () => {
+ if (emailInput.value.trim() && isValidEmail(emailInput.value)) {
+ clearError(emailInput, emailError);
+ }
+});
+
+userInfoForm.addEventListener('submit', (e) => {
+ e.preventDefault();
+ let isValid = true;
+
+ if (!nameInput.value.trim()) {
+ showError(nameInput, nameError, 'Please enter your name');
+ isValid = false;
+ nameInput.focus();
+ } else {
+ clearError(nameInput, nameError);
+ }
+
+ if (!emailInput.value.trim()) {
+ showError(emailInput, emailError, 'Please enter your email address');
+ isValid = false;
+ if (!nameError.textContent) {
+ emailInput.focus();
+ }
+ } else if (!isValidEmail(emailInput.value.trim())) {
+ showError(emailInput, emailError, 'Please enter a valid email address');
+ isValid = false;
+ if (!nameError.textContent) {
+ emailInput.focus();
+ }
+ } else {
+ clearError(emailInput, emailError);
+ }
+
+ if (isValid) {
+ userName = nameInput.value.trim();
+ const userInfoSection = document.getElementById('user-info-section');
+ const feedbackSection = document.getElementById('feedback-section');
+ userInfoSection.hidden = true;
+ feedbackSection.hidden = false;
+ feedbackSection.scrollIntoView({ behavior: 'smooth' });
+ document.querySelector('#feedback-form input[type="radio"]').focus();
+ }
+});
+
+const feedbackSection = document.getElementById('feedback-form');
+const resultsSection = document.getElementById('results');
+const form = document.getElementById('feedback-form');
+ const resultsContent =document.getElementById('results-content')
+ const feedbackDetails =document.querySelector('feedback-details')
+const progressFill =document.querySelector('progress-fill')
+ const progressText = document.querySelector('.progress-text')
+ let answeredQuestions = new Set();
+
+function updateProgress(){
+ const totalQuestion =2;
+const answeredCount = answeredQuestions.size;
+const percentage = (answeredCount / totalQuestion) * 100;
+
+progressFill.style.width = `${percentage}%`;
+progressText.textContent = `${answeredCount} of ${totalQuestion} sections completed`;
+announcer.textContent = `${answeredCount} of ${totalQuestion} sections completed`;
+}
+form.querySelectorAll('input[type="radio"]').forEach((radio) => {
+ radio.addEventListener('change', () => {
+ const questionName = radio.name;
+ answeredQuestions.add(questionName);
+ updateProgress();
+ });
+});
+form.addEventListener('submit', (e) => {
+ e.preventDefault();
+
+ const formData = new FormData(form);
+ const userAnswers = Object.fromEntries(formData);
+
+ let feedback = `Thank you for your feedback, ${userName}`;
+
+ const detailedFeedback =[];
+
+if (userAnswers.navigation === 'easy') {
+ detailedFeedback.push('Navigation: You found the site easy to navigate.');
+} else if (userAnswers.navigation === 'difficult') {
+ detailedFeedback.push('Navigation: You found the site difficult to navigate.');
+}
+
+if (userAnswers.readability === 'clear') {
+ detailedFeedback.push('Readability: Content is clear and readable.');
+} else if (userAnswers.readability === 'unclear') {
+ detailedFeedback.push('Readability: Content needs improvement.');
+}
+const userAnswerValues = Object.values(userAnswers);
+let positiveResponses = 0;
+
+for (const answer of userAnswerValues) {
+ if (answer === 'easy' || answer === 'clear') {
+ positiveResponses += 1;
+ }
+}
+ const totalResponses = Object.keys(userAnswers).length;
+ const satisfactionPercentage = Math.round((positiveResponses / totalResponses) * 100);
+ feedback = `Based on your responses, you seem ${satisfactionPercentage}% satisfied with our website.`;
+ feedback += positiveResponses >= totalResponses / 2
+ ? ' Thank you for your positive feedback!'
+ : ' We will work hard to improve.';
+
+ feedbackDetails.innerHTML = detailedFeedback.map((text) => `${text}
`).join('');
+ resultsSection.setAttribute('tabindex', '-1');
+ resultsSection.focus();
+ announcer.textContent = 'Feedback submitted. Your results are now displayed.';
+});
\ No newline at end of file
diff --git a/frontend/public/style.accessibility.css b/frontend/public/style.accessibility.css
new file mode 100644
index 00000000..092764ef
--- /dev/null
+++ b/frontend/public/style.accessibility.css
@@ -0,0 +1,640 @@
+* Base styles with accessibility considerations */
+:root {
+ --primary-color: #2c3e50;
+ --background-color: #ffffff;
+ --accent-color: #0040a3; /* Darker blue for better contrast */
+ --error-color: #e74c3c;
+ --success-color: #27ae60;
+ --focus-outline: 3px solid var(--accent-color);
+ --focus-ring-color: rgba(0, 86, 179, 0.5);
+ --progress-bg: #edf2f7;
+ --modal-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
+}
+
+/* Apply box-sizing border-box to all elements */
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+/* Modal Dialog */
+.modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.6);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+ backdrop-filter: blur(4px);
+}
+
+/* Ensure hidden attribute works properly */
+.modal[hidden] {
+ display: none;
+}
+
+.modal-content {
+ background-color: var(--background-color);
+ padding: 2rem;
+ border-radius: 8px;
+ max-width: 500px;
+ width: 90%;
+ max-height: 90vh;
+ overflow-y: auto;
+ box-shadow: var(--modal-shadow);
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ animation: modalAppear 0.3s ease-out;
+}
+
+@keyframes modalAppear {
+ from {
+ opacity: 0;
+ transform: translateY(-20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+/* Checkbox styling */
+.checkbox-container {
+ display: flex;
+ align-items: center;
+ margin-bottom: 0.5rem;
+}
+
+.checkbox-container input[type='checkbox'] {
+ width: auto;
+ margin-right: 0.5rem;
+}
+
+select {
+ width: 100%;
+ padding: 0.5rem;
+ font-size: 1rem;
+ border: 1px solid var(--secondary-color);
+ border-radius: 4px;
+}
+
+.checkbox-container label {
+ margin-bottom: 0;
+}
+.modal-body {
+ margin: 1.5rem 0;
+}
+
+.intro-section {
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.modal-footer {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 2rem;
+ gap: 1rem;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+ padding-top: 1.5rem;
+}
+
+#modal-title {
+ color: var(--primary-color);
+ margin: 0 0 1rem 0;
+ font-size: 1.5rem;
+ font-weight: 600;
+}
+
+.modal button {
+ padding: 0.75rem 1.5rem;
+ border-radius: 6px;
+ font-size: 1rem;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+#save-settings {
+ background-color: var(--accent-color);
+ color: white;
+ border: none;
+}
+
+#save-settings:hover {
+ background-color: #004494;
+}
+
+#close-modal {
+ background-color: transparent;
+ border: 1px solid var(--primary-color);
+ color: var(--primary-color);
+}
+
+#close-modal:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+
+/* Base styles for readability */
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial,
+ sans-serif;
+ line-height: 1.6;
+ color: var(--primary-color);
+ background-color: var(--background-color);
+ margin: 0;
+ padding: 20px;
+ font-size: 16px;
+ max-width: 800px;
+ margin: 0 auto;
+}
+
+/* Skip link with enhanced visibility */
+.skip-link {
+ position: absolute;
+ top: -40px;
+ left: 0;
+ background: var(--accent-color);
+ color: white;
+ padding: 8px;
+ z-index: 100;
+ transition: top 0.3s;
+}
+
+.skip-link:focus {
+ top: 0;
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+}
+
+/* Enhanced focus styles */
+:focus-visible {
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+ border-radius: 2px;
+}
+
+/* Progress bar styles */
+.quiz-progress {
+ margin: 2rem 0;
+}
+/* Images */
+.decorative-image,
+.info-image {
+ max-width: 15rem;
+ height: auto;
+ margin: 1rem 0;
+ border-radius: 4px;
+}
+
+.progress-bar {
+ background-color: var(--progress-bg);
+ border-radius: 8px;
+ height: 20px;
+ overflow: hidden;
+ position: relative;
+}
+
+.progress-fill {
+ background-color: var(--accent-color);
+ height: 100%;
+ transition: width 0.3s ease;
+ border-radius: 8px;
+}
+
+.progress-text {
+ margin-top: 0.5rem;
+ text-align: center;
+ font-weight: 500;
+}
+
+/* Question groups */
+.question-group {
+ margin-bottom: 2rem;
+ padding: 1rem;
+ border: 1px solid #e2e8f0;
+ border-radius: 8px;
+ background-color: #f8fafc;
+}
+
+.question-heading {
+ color: var(--primary-color);
+ margin-bottom: 1rem;
+ font-size: 1.1rem;
+}
+
+/* Form elements */
+fieldset {
+ border: 1px solid var(--primary-color);
+ margin: 1em 0;
+ padding: 1em;
+ border-radius: 4px;
+}
+
+legend {
+ font-weight: bold;
+ padding: 0.5em 1em;
+ color: var(--primary-color);
+ background-color: #f8fafc;
+ border: 1px solid var(--primary-color);
+ border-radius: 4px;
+}
+
+.radio-group {
+ margin: 1em 0;
+}
+
+/* Enhanced radio button styling */
+.radio-option {
+ position: relative;
+ padding: 0.75em;
+ margin: 0.5em 0;
+ border-radius: 4px;
+ transition: background-color 0.2s;
+ display: flex;
+ align-items: center;
+}
+
+.radio-option:hover {
+ background-color: rgba(52, 152, 219, 0.1);
+}
+
+/* Custom radio button styling */
+input[type='radio'] {
+ margin-right: 0.75em;
+ width: 20px;
+ height: 20px;
+}
+
+input[type='radio']:focus-visible + label {
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+ border-radius: 2px;
+}
+
+input[type='radio'] + label {
+ cursor: pointer;
+ padding: 4px 8px;
+ border-radius: 4px;
+ transition: background-color 0.2s;
+ flex: 1;
+}
+
+/* Instructions section */
+.quiz-instructions {
+ background-color: #f8f9fa;
+ padding: 1em;
+ margin: 1em 0;
+ border-left: 4px solid var(--accent-color);
+ border-radius: 0 4px 4px 0;
+}
+
+/* Submit button */
+.form-controls {
+ margin-top: 2rem;
+ text-align: center;
+}
+
+.submit-button {
+ background-color: var(--accent-color);
+ color: white;
+ border: none;
+ padding: 12px 24px;
+ font-size: 1rem;
+ cursor: pointer;
+ border-radius: 4px;
+ transition: background-color 0.2s, transform 0.1s;
+ font-weight: 500;
+}
+
+.submit-button:hover {
+ background-color: #2980b9;
+}
+
+.submit-button:active {
+ transform: scale(0.98);
+}
+
+.submit-button:focus-visible {
+ outline: var(--focus-outline);
+ outline-offset: 2px;
+}
+
+/* Results section */
+#results {
+ margin-top: 2rem;
+ padding: 1.5rem;
+ border-radius: 8px;
+ background-color: #f8fafc;
+ border: 1px solid var(--primary-color);
+}
+
+.feedback-details {
+ margin-top: 1rem;
+ padding: 1rem;
+ border-radius: 4px;
+}
+
+/* Utility classes */
+.visually-hidden {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+
+/* High contrast mode */
+@media (prefers-contrast: more) {
+ :root {
+ --primary-color: #000000;
+ --accent-color: #0000ee;
+ --focus-outline: 3px solid #000000;
+ }
+
+ header {
+ background: #ffffff;
+ border: 2px solid var(--primary-color);
+ }
+
+ nav a {
+ background-color: transparent;
+ border: 1px solid currentColor;
+ }
+
+ nav a:hover {
+ background-color: var(--primary-color);
+ }
+
+ .radio-option:hover {
+ background-color: #000000;
+ color: #ffffff;
+ }
+}
+
+/* Reduced motion */
+@media (prefers-reduced-motion: reduce) {
+ * {
+ transition-duration: 0.01ms !important;
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ scroll-behavior: auto !important;
+ }
+}
+
+/* Basic responsive design */
+@media (max-width: 600px) {
+ body {
+ padding: 10px;
+ }
+
+ fieldset {
+ padding: 0.5em;
+ }
+
+ header {
+ padding: 1.25rem;
+ }
+
+ nav ul {
+ gap: 0.75rem;
+ }
+}
+
+/* User Info Form */
+#user-info {
+ margin-bottom: 2rem;
+ padding: 1.5rem;
+ background-color: #f8fafc;
+ border-radius: 8px;
+ border: 1px solid #e2e8f0;
+}
+
+.form-control {
+ margin-bottom: 1.5rem;
+ position: relative;
+}
+
+.form-control label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+ color: var(--primary-color);
+}
+
+.form-control input {
+ width: 100%;
+ padding: 0.75rem;
+ font-size: 1rem;
+ border: 1px solid var(--primary-color);
+ border-radius: 4px;
+ transition: border-color 0.2s, box-shadow 0.2s;
+ box-sizing: border-box;
+}
+
+.form-control input:focus {
+ outline: none;
+ border-color: var(--accent-color);
+ box-shadow: 0 0 0 3px var(--focus-ring-color);
+}
+
+.form-control input[aria-invalid='true'] {
+ border-color: var(--error-color);
+}
+
+.form-control input[aria-invalid='true']:focus {
+ box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.25);
+}
+
+.error {
+ color: var(--error-color);
+ font-size: 0.875rem;
+ margin-top: 0.25rem;
+}
+
+.hint {
+ color: var(--secondary-color);
+ font-size: 0.875rem;
+ margin-top: 0.25rem;
+}
+
+/* Introduction section and images */
+#introduction {
+ padding: 2rem;
+ margin-bottom: 2rem;
+ background-color: #f8fafc;
+ border-radius: 12px;
+}
+
+#introduction h2 {
+ color: var(--primary-color);
+ font-size: 2rem;
+ margin-bottom: 1.5rem;
+}
+
+#introduction p {
+ max-width: 800px;
+ margin: 0 auto 2rem;
+}
+
+.hero-images {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 2rem;
+ margin: 2rem 0;
+}
+
+.decorative-image,
+.info-image {
+ max-width: 100%;
+ height: auto;
+ border-radius: 8px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+}
+
+.info-image {
+ padding: 1rem;
+ background: white;
+}
+
+@media (min-width: 768px) {
+ .hero-images {
+ flex-direction: row;
+ justify-content: center;
+ gap: 3rem;
+ }
+
+ .decorative-image,
+ .info-image {
+ width: 45%;
+ max-width: 400px;
+ }
+}
+
+/* Header and Navigation */
+header {
+ margin-bottom: 2rem;
+}
+
+h1,
+h2 {
+ margin-bottom: 1rem;
+}
+
+nav ul {
+ list-style: none;
+ padding: 0;
+ display: flex;
+ gap: 1rem;
+}
+
+nav a {
+ color: var(--accent-color);
+ text-decoration: none;
+}
+
+nav a:hover {
+ text-decoration: underline;
+}
+
+/* About page specific styles */
+#about {
+ padding: 3rem;
+ background-color: #f8fafc;
+ border-radius: 12px;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+}
+
+#about h2 {
+ color: #2c3e50;
+ font-size: 2.5rem;
+ margin-bottom: 1.5rem;
+ border-bottom: 3px solid #3498db;
+ padding-bottom: 0.5rem;
+ display: inline-block;
+}
+
+#about p {
+ font-size: 1.2rem;
+ line-height: 1.8;
+ color: #34495e;
+ margin-bottom: 2rem;
+ max-width: 700px;
+}
+
+#about .hero-images {
+ margin: 3rem 0;
+ display: flex;
+ justify-content: center;
+}
+
+#about .hero-images img {
+ max-width: 100%;
+ height: auto;
+ border-radius: 12px;
+ box-shadow: 0 6px 15px rgba(0, 0, 0, 0.1);
+ transition: transform 0.3s ease;
+}
+
+#about .hero-images img:hover {
+ transform: scale(1.02);
+}
+
+/* Header improvements */
+#header {
+ padding: 2rem 0;
+ margin-bottom: 3rem;
+ border-bottom: 1px solid #eaeaea;
+}
+
+#header nav ul {
+ list-style: none;
+ padding: 0;
+ margin: 1rem 0;
+ display: flex;
+ gap: 2rem;
+}
+
+#header nav a {
+ color: #0040a3; /* Darker blue for better contrast */
+ text-decoration: none;
+ font-size: 1.1rem;
+ font-weight: 500;
+ padding: 0.5rem 1rem;
+ border-radius: 6px;
+ transition: all 0.2s ease;
+}
+
+#header nav a:hover {
+ background-color: #0040a3;
+ color: white;
+ text-decoration: none;
+}
+
+/* Responsive adjustments */
+@media (max-width: 600px) {
+ #about {
+ padding: 1.5rem;
+ }
+
+ #about h2 {
+ font-size: 2rem;
+ }
+
+ #about p {
+ font-size: 1.1rem;
+ }
+
+ #header nav ul {
+ gap: 1rem;
+ }
+}
diff --git "a/frontend/public/svg/Johan Skarpsv\303\244rd@2x.svg" "b/frontend/public/svg/Johan Skarpsv\303\244rd@2x.svg"
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/Arrow.svg b/frontend/public/svg/images/Arrow.svg
new file mode 100644
index 00000000..e69de29b
diff --git "a/frontend/public/svg/images/Johan Skarpsv\303\244rd.svg" "b/frontend/public/svg/images/Johan Skarpsv\303\244rd.svg"
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/Tablet_745.png b/frontend/public/svg/images/Tablet_745.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/divder.svg b/frontend/public/svg/images/divder.svg
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/icon-6931507.svg b/frontend/public/svg/images/icon-6931507.svg
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/imag-5.png b/frontend/public/svg/images/imag-5.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-1.png b/frontend/public/svg/images/img-1.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-10.png b/frontend/public/svg/images/img-10.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-11.png b/frontend/public/svg/images/img-11.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-2.png b/frontend/public/svg/images/img-2.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-3.png b/frontend/public/svg/images/img-3.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-4.png b/frontend/public/svg/images/img-4.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-5.png b/frontend/public/svg/images/img-5.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-6.png b/frontend/public/svg/images/img-6.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-7.png b/frontend/public/svg/images/img-7.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-8.png b/frontend/public/svg/images/img-8.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img-9.png b/frontend/public/svg/images/img-9.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/img.png b/frontend/public/svg/images/img.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/thesis.-1.png b/frontend/public/svg/images/thesis.-1.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/images/thesis.png b/frontend/public/svg/images/thesis.png
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/johan b/frontend/public/svg/johan
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/linkedin.svg b/frontend/public/svg/linkedin.svg
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/svg/vite.config.js b/frontend/public/svg/vite.config.js
new file mode 100644
index 00000000..8d60bf7f
--- /dev/null
+++ b/frontend/public/svg/vite.config.js
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})
\ No newline at end of file
diff --git a/public/vite.svg b/frontend/public/svg/vite.svg
similarity index 100%
rename from public/vite.svg
rename to frontend/public/svg/vite.svg
diff --git a/frontend/public/useeffect/.gitignore b/frontend/public/useeffect/.gitignore
new file mode 100644
index 00000000..4d29575d
--- /dev/null
+++ b/frontend/public/useeffect/.gitignore
@@ -0,0 +1,23 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/frontend/public/useeffect/README.md b/frontend/public/useeffect/README.md
new file mode 100644
index 00000000..58beeacc
--- /dev/null
+++ b/frontend/public/useeffect/README.md
@@ -0,0 +1,70 @@
+# Getting Started with Create React App
+
+This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
+
+## Available Scripts
+
+In the project directory, you can run:
+
+### `npm start`
+
+Runs the app in the development mode.\
+Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
+
+The page will reload when you make changes.\
+You may also see any lint errors in the console.
+
+### `npm test`
+
+Launches the test runner in the interactive watch mode.\
+See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
+
+### `npm run build`
+
+Builds the app for production to the `build` folder.\
+It correctly bundles React in production mode and optimizes the build for the best performance.
+
+The build is minified and the filenames include the hashes.\
+Your app is ready to be deployed!
+
+See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
+
+### `npm run eject`
+
+**Note: this is a one-way operation. Once you `eject`, you can't go back!**
+
+If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
+
+Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
+
+You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
+
+## Learn More
+
+You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
+
+To learn React, check out the [React documentation](https://reactjs.org/).
+
+### Code Splitting
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
+
+### Analyzing the Bundle Size
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
+
+### Making a Progressive Web App
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
+
+### Advanced Configuration
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
+
+### Deployment
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
+
+### `npm run build` fails to minify
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
diff --git a/frontend/public/useeffect/package.json b/frontend/public/useeffect/package.json
new file mode 100644
index 00000000..c2ecd5da
--- /dev/null
+++ b/frontend/public/useeffect/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "useeffect",
+ "version": "0.1.0",
+ "private": true,
+ "dependencies": {
+ "@testing-library/dom": "^10.4.0",
+ "@testing-library/jest-dom": "^6.6.3",
+ "@testing-library/react": "^16.3.0",
+ "@testing-library/user-event": "^13.5.0",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "react-scripts": "5.0.1",
+ "web-vitals": "^2.1.4"
+ },
+ "scripts": {
+ "start": "react-scripts start",
+ "build": "react-scripts build",
+ "test": "react-scripts test",
+ "eject": "react-scripts eject"
+ },
+ "eslintConfig": {
+ "extends": [
+ "react-app",
+ "react-app/jest"
+ ]
+ },
+ "browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version"
+ ]
+ }
+}
diff --git a/frontend/public/useeffect/public/favicon.ico b/frontend/public/useeffect/public/favicon.ico
new file mode 100644
index 00000000..a11777cc
Binary files /dev/null and b/frontend/public/useeffect/public/favicon.ico differ
diff --git a/frontend/public/useeffect/public/index.html b/frontend/public/useeffect/public/index.html
new file mode 100644
index 00000000..aa069f27
--- /dev/null
+++ b/frontend/public/useeffect/public/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ React App
+
+
+ You need to enable JavaScript to run this app.
+
+
+
+
diff --git a/frontend/public/useeffect/public/logo192.png b/frontend/public/useeffect/public/logo192.png
new file mode 100644
index 00000000..fc44b0a3
Binary files /dev/null and b/frontend/public/useeffect/public/logo192.png differ
diff --git a/frontend/public/useeffect/public/logo512.png b/frontend/public/useeffect/public/logo512.png
new file mode 100644
index 00000000..a4e47a65
Binary files /dev/null and b/frontend/public/useeffect/public/logo512.png differ
diff --git a/frontend/public/useeffect/public/manifest.json b/frontend/public/useeffect/public/manifest.json
new file mode 100644
index 00000000..080d6c77
--- /dev/null
+++ b/frontend/public/useeffect/public/manifest.json
@@ -0,0 +1,25 @@
+{
+ "short_name": "React App",
+ "name": "Create React App Sample",
+ "icons": [
+ {
+ "src": "favicon.ico",
+ "sizes": "64x64 32x32 24x24 16x16",
+ "type": "image/x-icon"
+ },
+ {
+ "src": "logo192.png",
+ "type": "image/png",
+ "sizes": "192x192"
+ },
+ {
+ "src": "logo512.png",
+ "type": "image/png",
+ "sizes": "512x512"
+ }
+ ],
+ "start_url": ".",
+ "display": "standalone",
+ "theme_color": "#000000",
+ "background_color": "#ffffff"
+}
diff --git a/frontend/public/useeffect/public/robots.txt b/frontend/public/useeffect/public/robots.txt
new file mode 100644
index 00000000..e9e57dc4
--- /dev/null
+++ b/frontend/public/useeffect/public/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/frontend/public/useeffect/src/App.css b/frontend/public/useeffect/src/App.css
new file mode 100644
index 00000000..74b5e053
--- /dev/null
+++ b/frontend/public/useeffect/src/App.css
@@ -0,0 +1,38 @@
+.App {
+ text-align: center;
+}
+
+.App-logo {
+ height: 40vmin;
+ pointer-events: none;
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ .App-logo {
+ animation: App-logo-spin infinite 20s linear;
+ }
+}
+
+.App-header {
+ background-color: #282c34;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ font-size: calc(10px + 2vmin);
+ color: white;
+}
+
+.App-link {
+ color: #61dafb;
+}
+
+@keyframes App-logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
diff --git a/frontend/public/useeffect/src/App.js b/frontend/public/useeffect/src/App.js
new file mode 100644
index 00000000..37845757
--- /dev/null
+++ b/frontend/public/useeffect/src/App.js
@@ -0,0 +1,25 @@
+import logo from './logo.svg';
+import './App.css';
+
+function App() {
+ return (
+
+ );
+}
+
+export default App;
diff --git a/frontend/public/useeffect/src/App.test.js b/frontend/public/useeffect/src/App.test.js
new file mode 100644
index 00000000..1f03afee
--- /dev/null
+++ b/frontend/public/useeffect/src/App.test.js
@@ -0,0 +1,8 @@
+import { render, screen } from '@testing-library/react';
+import App from './App';
+
+test('renders learn react link', () => {
+ render( );
+ const linkElement = screen.getByText(/learn react/i);
+ expect(linkElement).toBeInTheDocument();
+});
diff --git a/frontend/public/useeffect/src/index.css b/frontend/public/useeffect/src/index.css
new file mode 100644
index 00000000..ec2585e8
--- /dev/null
+++ b/frontend/public/useeffect/src/index.css
@@ -0,0 +1,13 @@
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+ sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+code {
+ font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
+ monospace;
+}
diff --git a/frontend/public/useeffect/src/index.js b/frontend/public/useeffect/src/index.js
new file mode 100644
index 00000000..d563c0fb
--- /dev/null
+++ b/frontend/public/useeffect/src/index.js
@@ -0,0 +1,17 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import './index.css';
+import App from './App';
+import reportWebVitals from './reportWebVitals';
+
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render(
+
+
+
+);
+
+// If you want to start measuring performance in your app, pass a function
+// to log results (for example: reportWebVitals(console.log))
+// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
+reportWebVitals();
diff --git a/frontend/public/useeffect/src/logo.svg b/frontend/public/useeffect/src/logo.svg
new file mode 100644
index 00000000..9dfc1c05
--- /dev/null
+++ b/frontend/public/useeffect/src/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/public/useeffect/src/reportWebVitals.js b/frontend/public/useeffect/src/reportWebVitals.js
new file mode 100644
index 00000000..5253d3ad
--- /dev/null
+++ b/frontend/public/useeffect/src/reportWebVitals.js
@@ -0,0 +1,13 @@
+const reportWebVitals = onPerfEntry => {
+ if (onPerfEntry && onPerfEntry instanceof Function) {
+ import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
+ getCLS(onPerfEntry);
+ getFID(onPerfEntry);
+ getFCP(onPerfEntry);
+ getLCP(onPerfEntry);
+ getTTFB(onPerfEntry);
+ });
+ }
+};
+
+export default reportWebVitals;
diff --git a/frontend/public/useeffect/src/setupTests.js b/frontend/public/useeffect/src/setupTests.js
new file mode 100644
index 00000000..8f2609b7
--- /dev/null
+++ b/frontend/public/useeffect/src/setupTests.js
@@ -0,0 +1,5 @@
+// jest-dom adds custom jest matchers for asserting on DOM nodes.
+// allows you to do things like:
+// expect(element).toHaveTextContent(/react/i)
+// learn more: https://github.com/testing-library/jest-dom
+import '@testing-library/jest-dom';
diff --git a/frontend/public/vite-project/.gitignore b/frontend/public/vite-project/.gitignore
new file mode 100644
index 00000000..a547bf36
--- /dev/null
+++ b/frontend/public/vite-project/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/frontend/public/vite-project/App.js b/frontend/public/vite-project/App.js
new file mode 100644
index 00000000..99895235
--- /dev/null
+++ b/frontend/public/vite-project/App.js
@@ -0,0 +1,33 @@
+import { useEffect, useState } from 'react'
+import logo from './logo.svg';
+import './App.css';
+
+function App(){
+ const [count, setCount] = useState(0);
+ const [decrement, setDecrement] = useState(100);
+useEffect(() => {
+ console.log('mount');
+});
+return (
+
+
setCount(c =>c + 1)}>{count}
+
setDecrement(d => d - 1)}>{decrement}
+
+
+ );
+}
+
+export default App;
diff --git a/frontend/public/vite-project/README.md b/frontend/public/vite-project/README.md
new file mode 100644
index 00000000..3f5ef227
--- /dev/null
+++ b/frontend/public/vite-project/README.md
@@ -0,0 +1,17 @@
+# React + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend using TypeScript and enable type-aware lint rules. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
+A/RES/217(III)
+A/RES/70/1
+GDPR EU 2016/679
+The AI Act
+Copyright@Johan Skarpsvärd
diff --git a/frontend/public/vite-project/api/Deatail.js b/frontend/public/vite-project/api/Deatail.js
new file mode 100644
index 00000000..52ea1fc6
--- /dev/null
+++ b/frontend/public/vite-project/api/Deatail.js
@@ -0,0 +1,23 @@
+import React, { useState, useEffect } from 'react';
+import ReactDOM from "react-dom";
+export const Detail = (props) => {
+const [details, setDetails] = useState();
+useEffect(() => {
+ fetch(props.url)
+ .then(res => res.json())
+ .then(json => {
+ console.log(json)
+ setDetails(json);
+ });
+});
+return (
+
+
{props.name}
+ {details && (
+
{JSON.stringify(details, null, 2)}
+ )}
+ {details &&
}
+
+);
+}
+
diff --git a/frontend/public/vite-project/api/import React, {use b/frontend/public/vite-project/api/import React, {use
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/public/vite-project/api/index.js b/frontend/public/vite-project/api/index.js
new file mode 100644
index 00000000..d2a3eec8
--- /dev/null
+++ b/frontend/public/vite-project/api/index.js
@@ -0,0 +1,30 @@
+import React, { useState, useEffect } from "react";
+import ReactDOM from "react-dom";
+
+ const App = () => {
+ const [johanSkarpsvard, setJohanSkarpsvard] = useState([]);
+ const [selectedJohanSkarpsvard, setSelectedJohanSkarpsvard] = useState([]);
+ useEffect(() => {
+ fetch("https://johanSkarpsvard.api")
+ .then(res => res.json())
+ .then(json => setJohanSkarpsvard(json.results));
+ }, []);
+
+ return (
+
+
+ {johanSkarpsvard.map((johanskarpsvärd) => (
+
+ {johanskarpsvärd.name}
+ setSelectedJohanSkarpsvard(johanskarpsvärd)}>
+ {johanskarpsvärd.name}
+
+
+ ))}
+
+ {selectedJohanSkarpsvard &&
}
+
+ );
+ };
+ const rootElement = document.getElementById("root");
+ ReactDOM.render( , rootElement);
diff --git a/frontend/public/vite-project/eslint.config.js b/frontend/public/vite-project/eslint.config.js
new file mode 100644
index 00000000..ec2b712d
--- /dev/null
+++ b/frontend/public/vite-project/eslint.config.js
@@ -0,0 +1,33 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+
+export default [
+ { ignores: ['dist'] },
+ {
+ files: ['**/*.{js,jsx}'],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ parserOptions: {
+ ecmaVersion: 'latest',
+ ecmaFeatures: { jsx: true },
+ sourceType: 'module',
+ },
+ },
+ plugins: {
+ 'react-hooks': reactHooks,
+ 'react-refresh': reactRefresh,
+ },
+ rules: {
+ ...js.configs.recommended.rules,
+ ...reactHooks.configs.recommended.rules,
+ 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }],
+ 'react-refresh/only-export-components': [
+ 'warn',
+ { allowConstantExport: true },
+ ],
+ },
+ },
+]
diff --git a/frontend/public/vite-project/index.html b/frontend/public/vite-project/index.html
new file mode 100644
index 00000000..0c589ecc
--- /dev/null
+++ b/frontend/public/vite-project/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+ Vite + React
+
+
+
+
+
+
diff --git a/frontend/public/vite-project/index.js b/frontend/public/vite-project/index.js
new file mode 100644
index 00000000..344bbbe2
--- /dev/null
+++ b/frontend/public/vite-project/index.js
@@ -0,0 +1,21 @@
+import React from "react";
+import ReactDOM from "react-dom";
+
+import "./style.accessibility.css";
+
+const App = () => {
+ const [name, setName] = React.useState('');
+ return (
+
+ );
+};
+
+const rootElement = document.getElementById("root");
+ReactDOM.render( , rootElement);
\ No newline at end of file
diff --git a/frontend/public/vite-project/package.json b/frontend/public/vite-project/package.json
new file mode 100644
index 00000000..82d8df17
--- /dev/null
+++ b/frontend/public/vite-project/package.json
@@ -0,0 +1,29 @@
+{
+ "name": "vite-project",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "lint": "eslint .",
+ "test": "cypress open",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "cypress": "^14.3.0",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.21.0",
+ "@types/react": "^19.0.10",
+ "@types/react-dom": "^19.0.4",
+ "@vitejs/plugin-react": "^4.3.4",
+ "eslint": "^9.21.0",
+ "eslint-plugin-react-hooks": "^5.1.0",
+ "eslint-plugin-react-refresh": "^0.4.19",
+ "globals": "^15.15.0",
+ "vite": "^6.2.0"
+ }
+}
diff --git a/frontend/public/vite-project/public/components/card.css b/frontend/public/vite-project/public/components/card.css
new file mode 100644
index 00000000..40de99b1
--- /dev/null
+++ b/frontend/public/vite-project/public/components/card.css
@@ -0,0 +1,5 @@
+article {
+ border: 2px solid black;
+ padding: 1rem;
+ width: 400px;
+ }
\ No newline at end of file
diff --git a/frontend/public/vite-project/public/components/card.jsx b/frontend/public/vite-project/public/components/card.jsx
new file mode 100644
index 00000000..3cc744ce
--- /dev/null
+++ b/frontend/public/vite-project/public/components/card.jsx
@@ -0,0 +1,42 @@
+// const Card = () => My profile card component
+
+// const Card = () => (
+//
+// My profile card
+//
+// )
+
+// const Card = () => {
+// return (
+//
+// My profile card
+//
+// )
+// }
+
+// const Card = () => {
+// return (
+//
+// Johan Skarpsvärd
+//
+// )
+// }
+
+// const Card = (props) => {
+// return (
+//
+// {props.title}
+//
+// )
+// }
+
+const Card = ({ title, text }) => {
+ return (
+
+ {title}
+ {text}
+
+ )
+ }
+
+ export default Card
\ No newline at end of file
diff --git a/frontend/public/vite-project/public/vite.svg b/frontend/public/vite-project/public/vite.svg
new file mode 100644
index 00000000..e7b8dfb1
--- /dev/null
+++ b/frontend/public/vite-project/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/public/vite-project/src/App.css b/frontend/public/vite-project/src/App.css
new file mode 100644
index 00000000..b9d355df
--- /dev/null
+++ b/frontend/public/vite-project/src/App.css
@@ -0,0 +1,42 @@
+#root {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
diff --git a/frontend/public/vite-project/src/App.jsx b/frontend/public/vite-project/src/App.jsx
new file mode 100644
index 00000000..f67355ae
--- /dev/null
+++ b/frontend/public/vite-project/src/App.jsx
@@ -0,0 +1,35 @@
+import { useState } from 'react'
+import reactLogo from './assets/react.svg'
+import viteLogo from '/vite.svg'
+import './App.css'
+
+function App() {
+ const [count, setCount] = useState(0)
+
+ return (
+ <>
+
+ Vite + React
+
+
setCount((count) => count + 1)}>
+ count is {count}
+
+
+ Edit src/App.jsx and save to test HMR
+
+
+
+ Click on the Vite and React logos to learn more
+
+ >
+ )
+}
+
+export default App
diff --git a/frontend/public/vite-project/src/assets/react.svg b/frontend/public/vite-project/src/assets/react.svg
new file mode 100644
index 00000000..6c87de9b
--- /dev/null
+++ b/frontend/public/vite-project/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/frontend/public/vite-project/src/index.css b/frontend/public/vite-project/src/index.css
new file mode 100644
index 00000000..08a3ac9e
--- /dev/null
+++ b/frontend/public/vite-project/src/index.css
@@ -0,0 +1,68 @@
+:root {
+ font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
diff --git a/src/main.jsx b/frontend/public/vite-project/src/main.jsx
similarity index 85%
rename from src/main.jsx
rename to frontend/public/vite-project/src/main.jsx
index ed109d76..b9a1a6de 100644
--- a/src/main.jsx
+++ b/frontend/public/vite-project/src/main.jsx
@@ -1,9 +1,7 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
-
-import { App } from './App.jsx'
-
import './index.css'
+import App from './App.jsx'
createRoot(document.getElementById('root')).render(
diff --git a/frontend/public/vite-project/vite.config.js b/frontend/public/vite-project/vite.config.js
new file mode 100644
index 00000000..8b0f57b9
--- /dev/null
+++ b/frontend/public/vite-project/vite.config.js
@@ -0,0 +1,7 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react()],
+})
diff --git a/src/App.jsx b/frontend/src/App.jsx
similarity index 100%
rename from src/App.jsx
rename to frontend/src/App.jsx
diff --git a/frontend/src/assets/stores/appContentStore.jsx b/frontend/src/assets/stores/appContentStore.jsx
new file mode 100644
index 00000000..3f936b84
--- /dev/null
+++ b/frontend/src/assets/stores/appContentStore.jsx
@@ -0,0 +1,5 @@
+import {create} from "zustand"
+export const appContentStore = create(() => ({}))
+appContent:{
+ heading: "State-Management-Zustand-js-project-portfolio-Global Tech Development"
+}
\ No newline at end of file
diff --git a/frontend/src/assets/stores/components/Home.jsx b/frontend/src/assets/stores/components/Home.jsx
new file mode 100644
index 00000000..0e555f46
--- /dev/null
+++ b/frontend/src/assets/stores/components/Home.jsx
@@ -0,0 +1,6 @@
+import {appContentStore} from "../stores/appContentStore"
+export const Home () => {
+ const { appContent } = appContentStore()
+ return(
+ {appContent.heading}
+}
\ No newline at end of file
diff --git a/frontend/src/assets/stores/components/pages/SignupForm b/frontend/src/assets/stores/components/pages/SignupForm
new file mode 100644
index 00000000..8be5785b
--- /dev/null
+++ b/frontend/src/assets/stores/components/pages/SignupForm
@@ -0,0 +1,52 @@
+import { useState } from "react";
+
+const SignupForm = () => {
+ const [formData, setFormData] = useState({
+ email: "",
+ password: "",
+ });
+
+ const handleSubmit = (e) => {
+ e.preventDefault();
+ console.log(formData);
+
+ fetch("http://localhost:8080/users", {
+ method: "POST",
+ body: JSON.stringify({ email: formData.email, password: formData.password }),
+ headers: {
+ "Content-Type": "application/json"
+ }
+ })
+ .then(() => {
+ // Reset form
+ e.target.reset()
+ })
+ .catch(error => {
+ console.log(error)
+ })
+
+ };
+
+ return (
+
+ );
+};
+
+export default SignupForm;
\ No newline at end of file
diff --git a/frontend/src/assets/stores/components/pages/UserSettings.jsx b/frontend/src/assets/stores/components/pages/UserSettings.jsx
new file mode 100644
index 00000000..ef7fc4fc
--- /dev/null
+++ b/frontend/src/assets/stores/components/pages/UserSettings.jsx
@@ -0,0 +1,17 @@
+import { useUserStore } from "../stores/userstore"
+export const UserSettings = () => {
+ const { toggleLogin, } inCrementAge, setUserName} isLoggedIn, userName } = useUserStore()
+ return(
+
+
User Settings
+
Logged in: {isLoggedIn ? "Yes" : "No"}
+
Toggle Login
+
Increment Age
+
+ New User Name:
+ setUserName(event.target.value)}/>
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/frontend/src/assets/stores/components/pages/Userinfo.jsx b/frontend/src/assets/stores/components/pages/Userinfo.jsx
new file mode 100644
index 00000000..19415b8c
--- /dev/null
+++ b/frontend/src/assets/stores/components/pages/Userinfo.jsx
@@ -0,0 +1,11 @@
+import { useUserStore } from "../stores/userStore"
+export const UserInfo = () => {
+ const { userName, age } = useUserStore()
+
+return (
+
+}
User Profile
+
User Name: {userName}>
+
Age: {age}
+
+))
\ No newline at end of file
diff --git a/frontend/src/assets/stores/userStore.jsx b/frontend/src/assets/stores/userStore.jsx
new file mode 100644
index 00000000..67e4a179
--- /dev/null
+++ b/frontend/src/assets/stores/userStore.jsx
@@ -0,0 +1,9 @@
+import { create } from "zustand"
+export const useUserStore = create ((set) =>({
+ isLoggedIn: false,
+ age: 25,
+ userName: "John Doe",
+ toggleLogin: () set ((state) => ({isLoggedIn:})) !state.isLoggedIn}))
+ incrementAge: () => set ((state) => ({age: state.age +1})),
+ setUserName: (newUserName) => set ({userName:})
+})
\ No newline at end of file
diff --git a/src/data/projects.json b/frontend/src/data/projects.json
similarity index 96%
rename from src/data/projects.json
rename to frontend/src/data/projects.json
index 7c426028..462305ef 100644
--- a/src/data/projects.json
+++ b/frontend/src/data/projects.json
@@ -22,7 +22,7 @@
"APIs"
],
"netlify": "link",
- "github": "link"
+ "github": "link",
}
]
}
\ No newline at end of file
diff --git a/src/index.css b/frontend/src/index.css
similarity index 100%
rename from src/index.css
rename to frontend/src/index.css
diff --git a/gcrypt: b/gcrypt:
new file mode 100644
index 00000000..e69de29b
diff --git a/hello.cc: b/hello.cc:
new file mode 100644
index 00000000..98fa1f05
--- /dev/null
+++ b/hello.cc:
@@ -0,0 +1,153 @@
+// hello.cc
+#include
+
+namespace demo {
+
+using v8::FunctionCallbackInfo;
+using v8::Isolate;
+using v8::Local;
+using v8::NewStringType;
+using v8::Object;
+using v8::String;
+using v8::Value;
+
+void Method(const FunctionCallbackInfo& args) {
+ Isolate* isolate = args.GetIsolate();
+ args.GetReturnValue().Set(String::NewFromUtf8(
+ isolate, "world", NewStringType::kNormal).ToLocalChecked());
+}
+
+void Initialize(Local exports) {
+ NODE_SET_METHOD(exports, "hello", Method);
+}
+
+NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
+
+} // namespace demo
+void Initialize(Local exports);
+NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
+using namespace v8;
+
+extern "C" NODE_MODULE_EXPORT void
+NODE_MODULE_INITIALIZER(Local exports,
+ Local module,
+ Local context) {
+ /* Perform addon initialization steps here. */
+}
+static void DeleteInstance(void* data) {
+ // Cast `data` to an instance of the class and delete it.
+}
+#include
+
+using namespace v8;
+
+class AddonData {
+ public:
+ explicit AddonData(Isolate* isolate):
+ call_count(0) {
+ // Ensure this per-addon-instance data is deleted at environment cleanup.
+ node::AddEnvironmentCleanupHook(isolate, DeleteInstance, this);
+ }
+
+ // Per-addon data.
+ int call_count;
+
+ static void DeleteInstance(void* data) {
+ delete static_cast(data);
+ }
+};
+
+static void Method(const v8::FunctionCallbackInfo& info) {
+ // Retrieve the per-addon-instance data.
+ AddonData* data =
+ reinterpret_cast(info.Data().As()->Value());
+ data->call_count++;
+ info.GetReturnValue().Set((double)data->call_count);
+}
+
+// Initialize this addon to be context-aware.
+NODE_MODULE_INIT(/* exports, module, context */) {
+ Isolate* isolate = context->GetIsolate();
+
+ // Create a new instance of `AddonData` for this instance of the addon and
+ // tie its life cycle to that of the Node.js environment.
+ AddonData* data = new AddonData(isolate);
+
+ // Wrap the data in a `v8::External` so we can pass it to the method we
+ // expose.
+ Local external = External::New(isolate, data);
+
+ // Expose the method `Method` to JavaScript, and make sure it receives the
+ // per-addon-instance data we created above by passing `external` as the
+ // third parameter to the `FunctionTemplate` constructor.
+ exports->Set(context,
+ String::NewFromUtf8(isolate, "method").ToLocalChecked(),
+ FunctionTemplate::New(isolate, Method, external)
+ ->GetFunction(context).ToLocalChecked()).FromJust();
+}
+void AddEnvironmentCleanupHook(v8::Isolate* isolate,
+ void (*fun)(void* arg),
+ void* arg);
+ // addon.cc
+#include
+#include
+#include
+
+using node::AddEnvironmentCleanupHook;
+using v8::HandleScope;
+using v8::Isolate;
+using v8::Local;
+using v8::Object;
+
+// Note: In a real-world application, do not rely on static/global data.
+static char cookie[] = "yum yum";
+static int cleanup_cb1_called = 0;
+static int cleanup_cb2_called = 0;
+
+static void cleanup_cb1(void* arg) {
+ Isolate* isolate = static_cast(arg);
+ HandleScope scope(isolate);
+ Local obj = Object::New(isolate);
+ assert(!obj.IsEmpty()); // assert VM is still alive
+ assert(obj->IsObject());
+ cleanup_cb1_called++;
+}
+
+static void cleanup_cb2(void* arg) {
+ assert(arg == static_cast(cookie));
+ cleanup_cb2_called++;
+}
+
+static void sanity_check(void*) {
+ assert(cleanup_cb1_called == 1);
+ assert(cleanup_cb2_called == 1);
+}
+
+// Initialize this addon to be context-aware.
+NODE_MODULE_INIT(/* exports, module, context */) {
+ Isolate* isolate = context->GetIsolate();
+
+ AddEnvironmentCleanupHook(isolate, sanity_check, nullptr);
+ AddEnvironmentCleanupHook(isolate, cleanup_cb2, cookie);
+ AddEnvironmentCleanupHook(isolate, cleanup_cb1, isolate);
+}
+// test.js
+require('./build/Release/addon');
+{
+ "targets": [
+ {
+ "target_name": "addon",
+ "sources": [ "hello.cc" ]
+ }
+ ]
+}
+// hello.js
+const addon = require('./build/Release/addon');
+
+console.log(addon.hello());
+// Prints: 'world'
+try {
+ return require('./build/Release/addon.node');
+} catch (err) {
+ return require('./build/Debug/addon.node');
+}
\ No newline at end of file
diff --git a/index.html b/index.html
index 6676fb2d..999aa6df 100644
--- a/index.html
+++ b/index.html
@@ -4,10 +4,18 @@
- Portfolio
+ Portfolio Tech New Developer Johan Skarpsvärd
-
-
-
+
+
+
+
+
+
+
+
+
+
+