]> git.localhorst.tv Git - alttp.git/commitdiff
tech data model
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 17 Aug 2022 13:25:50 +0000 (15:25 +0200)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Wed, 17 Aug 2022 13:25:50 +0000 (15:25 +0200)
app/Http/Controllers/TechniqueController.php [new file with mode: 0644]
app/Models/Technique.php [new file with mode: 0644]
app/Policies/TechniquePolicy.php [new file with mode: 0644]
database/migrations/2022_08_03_074936_create_techniques_table.php [new file with mode: 0644]
resources/js/components/App.js
resources/js/components/pages/Technique.js [new file with mode: 0644]
resources/js/components/techniques/Detail.js [new file with mode: 0644]
routes/api.php

diff --git a/app/Http/Controllers/TechniqueController.php b/app/Http/Controllers/TechniqueController.php
new file mode 100644 (file)
index 0000000..97a45f0
--- /dev/null
@@ -0,0 +1,16 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\Technique;
+use Illuminate\Http\Request;
+
+class TechniqueController extends Controller
+{
+
+       public function single(Request $request, Technique $tech) {
+               $this->authorize('view', $tech);
+               return $tech->toJson();
+       }
+
+}
diff --git a/app/Models/Technique.php b/app/Models/Technique.php
new file mode 100644 (file)
index 0000000..202c455
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Technique extends Model
+{
+       use HasFactory;
+}
diff --git a/app/Policies/TechniquePolicy.php b/app/Policies/TechniquePolicy.php
new file mode 100644 (file)
index 0000000..3bebc88
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+
+namespace App\Policies;
+
+use App\Models\Technique;
+use App\Models\User;
+use Illuminate\Auth\Access\HandlesAuthorization;
+
+class TechniquePolicy
+{
+       use HandlesAuthorization;
+
+       /**
+        * Determine whether the user can view any models.
+        *
+        * @param  \App\Models\User  $user
+        * @return \Illuminate\Auth\Access\Response|bool
+        */
+       public function viewAny(?User $user = null)
+       {
+               return true;
+       }
+
+       /**
+        * Determine whether the user can view the model.
+        *
+        * @param  \App\Models\User  $user
+        * @param  \App\Models\Technique  $technique
+        * @return \Illuminate\Auth\Access\Response|bool
+        */
+       public function view(?User $user = null, Technique $technique)
+       {
+               return true;
+       }
+
+       /**
+        * Determine whether the user can create models.
+        *
+        * @param  \App\Models\User  $user
+        * @return \Illuminate\Auth\Access\Response|bool
+        */
+       public function create(User $user)
+       {
+               return $user->isAdmin();
+       }
+
+       /**
+        * Determine whether the user can update the model.
+        *
+        * @param  \App\Models\User  $user
+        * @param  \App\Models\Technique  $technique
+        * @return \Illuminate\Auth\Access\Response|bool
+        */
+       public function update(User $user, Technique $technique)
+       {
+               return $user->isAdmin();
+       }
+
+       /**
+        * Determine whether the user can delete the model.
+        *
+        * @param  \App\Models\User  $user
+        * @param  \App\Models\Technique  $technique
+        * @return \Illuminate\Auth\Access\Response|bool
+        */
+       public function delete(User $user, Technique $technique)
+       {
+               return $user->isAdmin();
+       }
+
+       /**
+        * Determine whether the user can restore the model.
+        *
+        * @param  \App\Models\User  $user
+        * @param  \App\Models\Technique  $technique
+        * @return \Illuminate\Auth\Access\Response|bool
+        */
+       public function restore(User $user, Technique $technique)
+       {
+               return $user->isAdmin();
+       }
+
+       /**
+        * Determine whether the user can permanently delete the model.
+        *
+        * @param  \App\Models\User  $user
+        * @param  \App\Models\Technique  $technique
+        * @return \Illuminate\Auth\Access\Response|bool
+        */
+       public function forceDelete(User $user, Technique $technique)
+       {
+               return $user->isAdmin();
+       }
+}
diff --git a/database/migrations/2022_08_03_074936_create_techniques_table.php b/database/migrations/2022_08_03_074936_create_techniques_table.php
new file mode 100644 (file)
index 0000000..5951115
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+       /**
+        * Run the migrations.
+        *
+        * @return void
+        */
+       public function up()
+       {
+               Schema::create('techniques', function (Blueprint $table) {
+                       $table->id();
+                       $table->string('name')->unique();
+                       $table->text('title');
+                       $table->text('short');
+                       $table->text('description');
+                       $table->timestamps();
+               });
+       }
+
+       /**
+        * Reverse the migrations.
+        *
+        * @return void
+        */
+       public function down()
+       {
+               Schema::dropIfExists('techniques');
+       }
+};
index e5d3578baa55b75f090401d520f128b920c1c1ac..1f188fb745d084d9080ee142114b340acdf54727 100644 (file)
@@ -4,6 +4,7 @@ import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
 
 import Header from './common/Header';
 import AlttpSeed from './pages/AlttpSeed';
+import Technique from './pages/Technique';
 import Tournament from './pages/Tournament';
 import User from './pages/User';
 import AlttpBaseRomProvider from '../helpers/AlttpBaseRomContext';
@@ -55,6 +56,7 @@ const App = () => {
                                <Header doLogout={doLogout} />
                                <Routes>
                                        <Route path="h/:hash" element={<AlttpSeed />} />
+                                       <Route path="tech/:name" element={<Technique />} />
                                        <Route path="tournaments/:id" element={<Tournament />} />
                                        <Route path="users/:id" element={<User />} />
                                        <Route path="*" element={<Navigate to="/tournaments/4" />} />
diff --git a/resources/js/components/pages/Technique.js b/resources/js/components/pages/Technique.js
new file mode 100644 (file)
index 0000000..19b56b7
--- /dev/null
@@ -0,0 +1,57 @@
+import axios from 'axios';
+import React, { useEffect, useState } from 'react';
+import { useParams } from 'react-router-dom';
+
+import ErrorBoundary from '../common/ErrorBoundary';
+import ErrorMessage from '../common/ErrorMessage';
+import Loading from '../common/Loading';
+import NotFound from '../pages/NotFound';
+import Detail from '../techniques/Detail';
+
+const Technique = () => {
+       const params = useParams();
+       const { name } = params;
+
+       const [error, setError] = useState(null);
+       const [loading, setLoading] = useState(true);
+       const [technique, setTechnique] = useState(null);
+
+       useEffect(() => {
+               const ctrl = new AbortController();
+               setLoading(true);
+               axios
+                       .get(`/api/tech/${name}`, { signal: ctrl.signal })
+                       .then(response => {
+                               setError(null);
+                               setLoading(false);
+                               setTechnique(response.data);
+                               window.document.title = response.data.title;
+                       })
+                       .catch(error => {
+                               setError(error);
+                               setLoading(false);
+                               setTechnique(null);
+                       });
+               return () => {
+                       ctrl.abort();
+               };
+       }, [name]);
+
+       if (loading) {
+               return <Loading />;
+       }
+
+       if (error) {
+               return <ErrorMessage error={error} />;
+       }
+
+       if (!technique) {
+               return <NotFound />;
+       }
+
+       return <ErrorBoundary>
+               <Detail technique={technique} />
+       </ErrorBoundary>;
+};
+
+export default Technique;
diff --git a/resources/js/components/techniques/Detail.js b/resources/js/components/techniques/Detail.js
new file mode 100644 (file)
index 0000000..88ce594
--- /dev/null
@@ -0,0 +1,17 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import { Container } from 'react-bootstrap';
+
+const Detail = ({ technique }) => <Container>
+       <h1>{technique.title}</h1>
+       <div dangerouslySetInnerHTML={{ __html: technique.description }} />
+</Container>;
+
+Detail.propTypes = {
+       technique: PropTypes.shape({
+               description: PropTypes.string,
+               title: PropTypes.string,
+       }),
+};
+
+export default Detail;
index 1b0ea84e4a065335e9e2d4247d8ba0ec0c2980ec..7ae308e223cdc6618f6f7cbd2fc6d6706386f1c7 100644 (file)
@@ -42,6 +42,8 @@ Route::post('rounds/{round}/lock', 'App\Http\Controllers\RoundController@lock');
 Route::post('rounds/{round}/setSeed', 'App\Http\Controllers\RoundController@setSeed');
 Route::post('rounds/{round}/unlock', 'App\Http\Controllers\RoundController@unlock');
 
+Route::get('tech/{tech:name}', 'App\Http\Controllers\TechniqueController@single');
+
 Route::get('tournaments/{id}', 'App\Http\Controllers\TournamentController@single');
 Route::post('tournaments/{tournament}/apply', 'App\Http\Controllers\TournamentController@apply');
 Route::post('tournaments/{tournament}/close', 'App\Http\Controllers\TournamentController@close');