Initial commit

This commit is contained in:
MrFry 2020-03-07 08:09:01 +01:00
commit d0a48513e9
28 changed files with 724 additions and 0 deletions

22
package.json Normal file
View file

@ -0,0 +1,22 @@
{
"name": "nextClient",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"next": "^9.2.2",
"react": "^16.13.0",
"react-dom": "^16.13.0"
},
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}

View file

@ -0,0 +1,30 @@
.subjectSelector {
overflow: scroll;
height: 200px;
margin: 10px;
}
.subjItem {
font-size: 18px;
padding: 3px;
cursor: pointer;
}
.activeSubjItem {
background-color: var(--text-color);
color: black;
}
.searchBar {
margin: 10px;
width: 100%;
color: white;
background-color: #212127;
border: none;
font-size: 18px;
}
.subjItem:hover:not(.activeSubjItem) {
background-color: #555;
color: white;
}

View file

@ -0,0 +1,100 @@
import React, { PureComponent } from 'react'
import LoadingIndicator from '../LoadingIndicator'
import Subject from '../../components/Subject'
import constants from '../../constants.json'
import './AllQuestions.css'
class AllQuestions extends PureComponent {
constructor (props) {
super(props)
this.state = {
loaded: false,
activeSubjName: '',
searchTerm: ''
}
console.info('Fetching data')
fetch(`${constants.serverUrl}data.json`) // eslint-disable-line
.then((resp) => {
return resp.json()
})
.then((data) => {
this.data = data
this.setState({
loaded: true
})
})
}
onSubjSelect (name) {
this.setState({
activeSubjName: name
})
}
searchBarOnChange (e) {
let text = e.target.value
this.setState({
searchTerm: text
})
}
render () {
const { loaded, activeSubjName, searchTerm } = this.state
if (loaded) {
let currSubj = this.data.Subjects.find((subj) => {
return subj.Name === activeSubjName
})
return (
<div>
<div>
<input
placeholder='Keresés...'
className='searchBar'
type='text'
value={searchTerm}
onChange={this.searchBarOnChange.bind(this)}
/>
</div>
<div className='subjectSelector'>
{this.data.Subjects.map((subj, i) => {
if (!subj.Name.toLowerCase().includes(searchTerm.toLowerCase())) {
return null
}
return (
<div
className={activeSubjName === subj.Name
? 'subjItem activeSubjItem'
: 'subjItem'
}
key={i}
onClick={() => this.onSubjSelect(subj.Name)}
>
{subj.Name}
</div>
)
})}
</div>
<hr />
<div>
<Subject
subj={currSubj}
/>
</div>
</div>
)
} else {
return (
<LoadingIndicator />
)
}
}
}
export default AllQuestions

View file

@ -0,0 +1 @@
export { default } from './AllQuestions'

View file

View file

@ -0,0 +1,14 @@
import React, { PureComponent } from 'react'
import './Feedback.css'
class Feedback extends PureComponent {
render () {
return (
<div>
hello Feedback
</div>
)
}
}
export default Feedback

View file

@ -0,0 +1 @@
export { default } from './Feedback'

View file

@ -0,0 +1,3 @@
.link {
margin: 10px;
}

View file

@ -0,0 +1,30 @@
import React, { PureComponent } from 'react'
import './HomeTab.css'
import links from './links.json'
class HomeTab extends PureComponent {
render () {
return (
<div>
{Object.keys(links).map((key) => {
let link = links[key]
return (
<div
className='link'
key={key}
>
<a
href={link.href}
>
{link.text}
</a>
</div>
)
})}
</div>
)
}
}
export default HomeTab

View file

@ -0,0 +1 @@
export { default } from './HomeTab'

View file

@ -0,0 +1,18 @@
{
"install": {
"href": "/install",
"text": "Install"
},
"server": {
"href": "/servergit",
"text": "Szerver repó"
},
"client": {
"href": "/scriptgit",
"text": "Script git"
},
"classes": {
"href": "/classesgit",
"text": "Classes git"
}
}

View file

@ -0,0 +1,10 @@
.loadingindicator {
position: fixed;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
color: #fff;
font-size: 30px;
}

View file

@ -0,0 +1,14 @@
import React, { PureComponent } from 'react'
import './LoadingIndicator.css'
class LoadingIndicator extends PureComponent {
render () {
return (
<div className='loadingindicator'>
Loading...
</div>
)
}
}
export default LoadingIndicator

View file

@ -0,0 +1 @@
export { default } from './LoadingIndicator'

View file

View file

@ -0,0 +1,49 @@
import React, { PureComponent } from 'react'
import LoadingIndicator from '../LoadingIndicator'
import constants from '../../constants.json'
import './Manual.css'
class Manual extends PureComponent {
constructor (props) {
super(props)
this.state = {
loaded: false
}
console.info('Fetching manual')
fetch(`${constants.serverUrl}manual`) // eslint-disable-line
.then((resp) => {
return resp.text()
})
.then((data) => {
this.manual = {
__html: data
}
this.setState({
loaded: true
})
})
}
render () {
const { loaded } = this.state
if (loaded) {
return (
<div>
<div dangerouslySetInnerHTML={this.manual} />
</div>
)
} else {
return (
<LoadingIndicator />
)
}
}
}
export default Manual

View file

@ -0,0 +1 @@
export { default } from './Manual'

View file

@ -0,0 +1,22 @@
.questionContainer {
margin: 10px;
}
.questionContainer:hover {
background-color: var(--hoover-color);
}
.question {
font-weight: bold;
font-size: 17px;
color: #ffffff;
}
.answer {
font-size: 15px;
}
.data {
font-size: 13px;
color: #a1a1a1;
}

View file

@ -0,0 +1,34 @@
import React, { PureComponent } from 'react'
import './Question.css'
class Question extends PureComponent {
render () {
const { question } = this.props
let qdata = question.data
if (typeof qdata === 'object' && qdata.type === 'simple') {
qdata = ''
}
if (qdata) {
try {
qdata = JSON.stringify(qdata)
} catch (e) {}
}
return (
<div className='questionContainer'>
<div className='question'>
{question.Q}
</div>
<div className='answer'>
{question.A}
</div>
<div className='data'>
{qdata || null}
</div>
</div>
)
}
}
export default Question

View file

@ -0,0 +1 @@
export { default } from './Question'

View file

View file

@ -0,0 +1,31 @@
import React, { PureComponent } from 'react'
import Question from '../Question'
import './Subject.css'
class Subject extends PureComponent {
render () {
const { subj } = this.props
if (subj) {
return (
<div >
{subj.Questions.map((question, i) => {
return (
<Question
key={i}
question={question}
/>
)
})}
</div>
)
} else {
return (
<div />
)
}
}
}
export default Subject

View file

@ -0,0 +1 @@
export { default } from './Subject'

View file

@ -0,0 +1,28 @@
.uquestioncontainer {
margin: 5px;
}
.uquestioncontainer:hover {
background-color: var(--hoover-color);
}
.uquestionscontainer {
margin: 10px;
}
.uquestion {
font-weight: 'bold';
font-size: 16px;
color: #fff;
margin: 5px;
}
.uanswer {
margin: 5px;
}
.uquestionnumber {
color: #fff;
margin: 5px;
font-size: 20px;
}

View file

@ -0,0 +1,66 @@
import React, { PureComponent } from 'react'
import LoadingIndicator from '../LoadingIndicator'
import constants from '../../constants.json'
import './UserQuestions.css'
class UserQuestions extends PureComponent {
constructor (props) {
super(props)
this.state = {
loaded: false
}
console.info('Fetching qa.json')
fetch(`${constants.serverUrl}qa.json`) // eslint-disable-line
.then((resp) => {
return resp.json()
})
.then((data) => {
this.qa = data
this.setState({
loaded: true
})
})
}
render () {
const { loaded } = this.state
if (loaded) {
let questions = Object.keys(this.qa).map((key, i) => {
let q = this.qa[key]
return (
<div key={key} className='uquestioncontainer'>
<div >
<div className='uquestionnumber'>
{key}:
</div>
<div className='uquestion'>
{q.q}
</div>
</div>
<div className='uanswer'>
{q.a}
</div>
</div>
)
}).reverse()
return (
<div className='uquestionscontainer'>
{questions}
</div>
)
} else {
return (
<LoadingIndicator />
)
}
}
}
export default UserQuestions

View file

@ -0,0 +1 @@
export { default } from './UserQuestions'

118
src/pages/Home.css Normal file
View file

@ -0,0 +1,118 @@
body {
font: normal 14px Verdana;
color: #999999;
}
.link {
margin: 20px;
font-size: 20px;
}
.sidebarLink {
color: var(--text-color);
text-decoration: none;
}
.sidebar {
margin: 0;
padding: 0;
width: 200px;
background-color: #212127;
position: fixed;
height: 100%;
overflow: auto;
}
.sidebar a {
display: block;
color: black;
padding: 16px;
text-decoration: none;
color: var(--bright-color);
}
.sidebar a.active {
background-color: var(--text-color);
color: black;
}
.sidebar a:hover:not(.active) {
background-color: #555;
color: white;
}
div.content {
margin-left: 200px;
padding: 1px 16px;
}
.menuicon div {
height: 5px;
background-color: var(--bright-color);
margin: 0px 0;
display: none;
width: 30px;
}
.sidebarheader {
font-size: 40px;
color: var(--bright-color);
display: flex;
text-align: center;
}
.headercontainer {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: nowrap;
position: relative;
margin: 10px;
}
@media screen and (max-width: 700px) {
.sidebar {
width: 100%;
height: auto;
position: relative;
}
.sidebar a {float: left;}
div.content {margin-left: 0;}
}
@media screen and (max-width: 700px) {
.menuicon div {
display: block;
margin: 6px 0;
}
.sidebar a {
text-align: center;
float: none;
}
.menuicon {
display: inline;
}
.sidebaritemsconainer {
display: inline;
}
.sidebarheader {
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
}
.codecontainer {
margin-left: 0px;
margin-right: 0px;
}
.sitedescription {
width: 100%;
margin: 0 auto;
}
}

127
src/pages/Home.js Normal file
View file

@ -0,0 +1,127 @@
import React, { PureComponent } from 'react'
import AllQuestions from '../../components/AllQuestions'
import Manual from '../../components/Manual'
import HomeTab from '../../components/HomeTab'
import UserQuestions from '../../components/UserQuestions'
import Feedback from '../../components/Feedback'
import constants from '../../constants.json'
import './Home.css'
// TODO: css remove unnecesarry stuff
// TODO: home to separate component
// TODO: resizing test
// TODO: fetch data only once?
const tabs = {
home: {
text: 'Home',
component: HomeTab
},
allq: {
text: 'All questions',
component: AllQuestions
},
manual: {
text: 'Manual',
component: Manual
},
userq: {
text: 'User Questions',
component: UserQuestions
},
feedback: {
text: 'Feedback',
component: Feedback
}
}
class Home extends PureComponent {
constructor (props) {
super(props)
this.state = {
menuShowing: window.innerWidth > constants.mobileWindowWidth,
currentTab: 'home'
}
}
closeMenu () {
this.setState((oldState) => {
return {
menuShowing: !oldState.menuShowing
}
})
}
setActiveTab (name) {
this.setState({
currentTab: name
})
if (window.innerWidth < constants.mobileWindowWidth) {
this.setState({
menuShowing: false
})
}
}
renderSideBar () {
const { currentTab, menuShowing } = this.state
return (
<div className='sidebar'>
<div className='headercontainer'>
<span onClick={this.closeMenu.bind(this)} className='menuicon'>
<div />
<div />
<div />
</span>
<div className='sidebarheader' >
Frylabs
</div>
</div>
{
menuShowing
? <div className='sidebaritemsconainer'>
{Object.keys(tabs).map((key) => {
let tab = tabs[key]
return (
<a
key={key}
className={currentTab === key ? 'active' : ''}
href={'#' + key}
onClick={() => { this.setActiveTab(key) }}
>{tab.text}</a>
)
})}
</div>
: null
}
</div>
)
}
renderContents () {
const { currentTab } = this.state
let ContentComponent = tabs[currentTab].component
return (
<ContentComponent />
)
}
render () {
return (
<div>
{this.renderSideBar()}
<div className='content'>
{this.renderContents()}
</div>
</div>
)
}
}
export default Home