Merge branch 'master' into 'production'
Master See merge request Romulus21/portal!35
This commit is contained in:
41
app/Http/Controllers/ToDoController.php
Normal file
41
app/Http/Controllers/ToDoController.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Resources\ToDo as ToDoResource;
|
||||||
|
use App\Http\Resources\ToDoList as ToDoListResource;
|
||||||
|
use App\Models\ToDo;
|
||||||
|
use App\Models\ToDoList;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ToDoController extends Controller
|
||||||
|
{
|
||||||
|
public function store(ToDoList $toDoList)
|
||||||
|
{
|
||||||
|
$this->authorize('create', ToDoList::class);
|
||||||
|
|
||||||
|
$toDo = $toDoList->toDos()->create($this->validateData());
|
||||||
|
|
||||||
|
return (new ToDoResource($toDo))
|
||||||
|
->response()
|
||||||
|
->setStatusCode(201);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(ToDoList $toDoList, ToDo $toDo)
|
||||||
|
{
|
||||||
|
$this->authorize('update', $toDoList);
|
||||||
|
|
||||||
|
$toDo->update($this->validateData());
|
||||||
|
|
||||||
|
return (new ToDoResource($toDo))
|
||||||
|
->response()
|
||||||
|
->setStatusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validateData()
|
||||||
|
{
|
||||||
|
return request()->validate([
|
||||||
|
'name' => 'required',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
55
app/Http/Controllers/ToDoListController.php
Normal file
55
app/Http/Controllers/ToDoListController.php
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Resources\ToDoList as ToDoListResource;
|
||||||
|
use App\Models\ToDoList;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ToDoListController extends Controller
|
||||||
|
{
|
||||||
|
public function store()
|
||||||
|
{
|
||||||
|
$this->authorize('create', ToDoList::class);
|
||||||
|
|
||||||
|
$toDoList = request()->user()->toDoLists()->create($this->validateData());
|
||||||
|
|
||||||
|
return (new ToDoListResource($toDoList))
|
||||||
|
->response()
|
||||||
|
->setStatusCode(201);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(ToDoList $toDoList)
|
||||||
|
{
|
||||||
|
$this->authorize('view', $toDoList);
|
||||||
|
|
||||||
|
return new ToDoListResource($toDoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(ToDoList $toDoList)
|
||||||
|
{
|
||||||
|
$this->authorize('update', $toDoList);
|
||||||
|
|
||||||
|
$toDoList->update($this->validateData());
|
||||||
|
|
||||||
|
return (new ToDoListResource($toDoList))
|
||||||
|
->response()
|
||||||
|
->setStatusCode(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(ToDoList $toDoList)
|
||||||
|
{
|
||||||
|
$this->authorize('delete', $toDoList);
|
||||||
|
|
||||||
|
$toDoList->delete();
|
||||||
|
|
||||||
|
return response([], 204);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validateData()
|
||||||
|
{
|
||||||
|
return request()->validate([
|
||||||
|
'name' => 'required',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
35
app/Http/Resources/ToDo.php
Normal file
35
app/Http/Resources/ToDo.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ToDo extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'data' => [
|
||||||
|
'type' => 'to-dos',
|
||||||
|
'to_do_id' => $this->id,
|
||||||
|
'attributes' => [
|
||||||
|
'data' => [
|
||||||
|
'name' => $this->name,
|
||||||
|
'order' => $this->order,
|
||||||
|
'checked_at' => optional($this->checked_at)->diffForHumans(),
|
||||||
|
'last_updated' => $this->updated_at->diffForHumans(),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'links' => [
|
||||||
|
'self' => url('/to-do-lists/'.$this->to_do_list_id),
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
22
app/Http/Resources/ToDoCollection.php
Normal file
22
app/Http/Resources/ToDoCollection.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||||
|
|
||||||
|
class ToDoCollection extends ResourceCollection
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource collection into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'data' => $this->collection,
|
||||||
|
'to_dos_count' => $this->count(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
38
app/Http/Resources/ToDoList.php
Normal file
38
app/Http/Resources/ToDoList.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use App\Http\Resources\User as UserResource;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
class ToDoList extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($request)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'data' => [
|
||||||
|
'type' => 'to-do-lists',
|
||||||
|
'to_do_list_id' => $this->id,
|
||||||
|
'attributes' => [
|
||||||
|
'data' => [
|
||||||
|
'name' => $this->name,
|
||||||
|
'to_dos' => new ToDoCollection($this->toDos),
|
||||||
|
'posted_by' => new UserResource($this->user),
|
||||||
|
'last_updated' => $this->updated_at->diffForHumans(),
|
||||||
|
// 'cover_image' => new ImageResource($this->coverImage),
|
||||||
|
]
|
||||||
|
]
|
||||||
|
//'tags' => TagResource::collection($this->tags),
|
||||||
|
],
|
||||||
|
'links' => [
|
||||||
|
'self' => $this->path(),
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
18
app/Models/ToDo.php
Normal file
18
app/Models/ToDo.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
class ToDo extends Model
|
||||||
|
{
|
||||||
|
protected $guarded = [];
|
||||||
|
|
||||||
|
protected $dates = ['checked_at'];
|
||||||
|
|
||||||
|
public function toDoList() :BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(ToDoList::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
app/Models/ToDoList.php
Normal file
28
app/Models/ToDoList.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
|
class ToDoList extends Model
|
||||||
|
{
|
||||||
|
protected $guarded = [];
|
||||||
|
|
||||||
|
public function path()
|
||||||
|
{
|
||||||
|
return '/to-do-lists/' . $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function users(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toDos(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(ToDo::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ namespace App;
|
|||||||
|
|
||||||
use App\Models\Image;
|
use App\Models\Image;
|
||||||
use App\Models\Memo;
|
use App\Models\Memo;
|
||||||
|
use App\Models\ToDoList;
|
||||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||||
@@ -82,4 +83,9 @@ class User extends Authenticatable
|
|||||||
$userImage->path = 'images/default-cover.jpg';
|
$userImage->path = 'images/default-cover.jpg';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function toDoLists(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(ToDoList::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
94
app/Policies/ToDoListPolicy.php
Normal file
94
app/Policies/ToDoListPolicy.php
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Models\ToDoList;
|
||||||
|
use App\User;
|
||||||
|
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||||
|
|
||||||
|
class ToDoListPolicy
|
||||||
|
{
|
||||||
|
use HandlesAuthorization;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any to do lists.
|
||||||
|
*
|
||||||
|
* @param \App\User $user
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function viewAny(User $user)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the to do list.
|
||||||
|
*
|
||||||
|
* @param \App\User $user
|
||||||
|
* @param \App\Models\ToDoList $toDoList
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function view(User $user, ToDoList $toDoList)
|
||||||
|
{
|
||||||
|
return $user->id == $toDoList->user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create to do lists.
|
||||||
|
*
|
||||||
|
* @param \App\User $user
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function create(User $user)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the to do list.
|
||||||
|
*
|
||||||
|
* @param \App\User $user
|
||||||
|
* @param \App\Models\ToDoList $toDoList
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function update(User $user, ToDoList $toDoList)
|
||||||
|
{
|
||||||
|
return $user->id == $toDoList->user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the to do list.
|
||||||
|
*
|
||||||
|
* @param \App\User $user
|
||||||
|
* @param \App\Models\ToDoList $toDoList
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function delete(User $user, ToDoList $toDoList)
|
||||||
|
{
|
||||||
|
return $user->id == $toDoList->user_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can restore the to do list.
|
||||||
|
*
|
||||||
|
* @param \App\User $user
|
||||||
|
* @param \App\Models\ToDoList $toDoList
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function restore(User $user, ToDoList $toDoList)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can permanently delete the to do list.
|
||||||
|
*
|
||||||
|
* @param \App\User $user
|
||||||
|
* @param \App\Models\ToDoList $toDoList
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function forceDelete(User $user, ToDoList $toDoList)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ class AuthServiceProvider extends ServiceProvider
|
|||||||
// 'App\Model' => 'App\Policies\ModelPolicy',
|
// 'App\Model' => 'App\Policies\ModelPolicy',
|
||||||
'App\User' => 'App\Policies\UserPolicy',
|
'App\User' => 'App\Policies\UserPolicy',
|
||||||
'App\Models\Memo' => 'App\Policies\MemoPolicy',
|
'App\Models\Memo' => 'App\Policies\MemoPolicy',
|
||||||
|
'App\Models\ToDoList' => 'App\Policies\ToDoListPolicy',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
13
database/factories/ToDoListFactory.php
Normal file
13
database/factories/ToDoListFactory.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/** @var \Illuminate\Database\Eloquent\Factory $factory */
|
||||||
|
|
||||||
|
use App\Models\ToDoList;
|
||||||
|
use Faker\Generator as Faker;
|
||||||
|
|
||||||
|
$factory->define(ToDoList::class, function (Faker $faker) {
|
||||||
|
return [
|
||||||
|
'user_id' => factory(\App\User::class),
|
||||||
|
'name' => $faker->words(3, [false]),
|
||||||
|
];
|
||||||
|
});
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateToDoListsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('to_do_lists', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedBigInteger('user_id');
|
||||||
|
$table->string('name');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('to_do_lists');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateToDosTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('to_dos', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedBigInteger('to_do_list_id');
|
||||||
|
$table->string('name');
|
||||||
|
$table->integer('order')->default(0);
|
||||||
|
$table->timestamp('checked_at')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('to_dos');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
"eslint-plugin-vue": "^6.2.2",
|
"eslint-plugin-vue": "^6.2.2",
|
||||||
"laravel-mix": "^5.0.1",
|
"laravel-mix": "^5.0.1",
|
||||||
"laravel-mix-eslint": "^0.1.3",
|
"laravel-mix-eslint": "^0.1.3",
|
||||||
|
"laravel-mix-purgecss": "^5.0.0-rc.2",
|
||||||
"lodash": "^4.17.13",
|
"lodash": "^4.17.13",
|
||||||
"resolve-url-loader": "^2.3.1",
|
"resolve-url-loader": "^2.3.1",
|
||||||
"sass": "^1.20.1",
|
"sass": "^1.20.1",
|
||||||
@@ -32,6 +33,7 @@
|
|||||||
"dropzone": "^5.7.0",
|
"dropzone": "^5.7.0",
|
||||||
"laravel-mix-svg-vue": "^0.2.6",
|
"laravel-mix-svg-vue": "^0.2.6",
|
||||||
"markdown-it": "^10.0.0",
|
"markdown-it": "^10.0.0",
|
||||||
"markdown-it-checkbox": "^1.1.0"
|
"markdown-it-checkbox": "^1.1.0",
|
||||||
|
"tailwindcss": "^1.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex">
|
<div class="flex bg-orange-200 h-screen overflow-y-hidden">
|
||||||
<Nav />
|
<Nav />
|
||||||
<div v-if="authUser" class="w-100">
|
<div v-if="authUser" class="w-full overflow-y-auto">
|
||||||
<TopBar />
|
<TopBar />
|
||||||
<main>
|
<main>
|
||||||
<router-view :key="$route.fullPath" class="main"></router-view>
|
<router-view :key="$route.fullPath"></router-view>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="flex justify-center items-center rounded-full bg-orange-600 hover:bg-orange-800">
|
||||||
<img v-if="avatar" src="avatar" alt="alt" class="avatar" v-bind:class="'avatar' + size">
|
<img v-if="avatar" src="avatar" alt="alt" class="avatar" v-bind:class="'avatar' + size">
|
||||||
<span v-else class="avatar" v-bind:class="'avatar-' + size">{{ alt[0] }}</span>
|
<span v-else class="text-2xl font-bold" v-bind:class="'text-' + size">{{ alt[0] }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative mt-1">
|
<div class="relative mb-2">
|
||||||
<label :for="name" class="pb-1">{{ label }}</label>
|
<label :for="name" class="pb-2 font-bold text-xl ml-1">{{ label }}</label>
|
||||||
<input :id="name" :type="type" :placeholder="placeholder" v-model="value" @input="updateField()" :class="errorClassObject()">
|
<input :id="name" :type="type" :placeholder="placeholder" v-model="value" @input="updateField()" :class="errorClassObject()" class="w-full rounded p-2">
|
||||||
<p class="text-alert m-0" v-text="errorMessage()">Error Here</p>
|
<p class="text-red-600 m-0" v-text="errorMessage()">Error Here</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="loading" class="flex-center">
|
<div v-if="loading" class="flex items-center">
|
||||||
<svg-vue icon="loader" class="loader"/>
|
<svg-vue icon="loader" class="loader"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav v-bind:class="{ small: !toggleNav }">
|
<nav v-bind:class="{ small: !toggleNav }" class="h-screen bg-orange-400 flex flex-col justify-between">
|
||||||
<router-link to="/" class="site-logo-main" v-bind:class="{ small: !toggleNav }">
|
<div class="">
|
||||||
|
<router-link to="/" class="logo" v-bind:class="{ small: !toggleNav }">
|
||||||
<svg-vue icon="logo" />
|
<svg-vue icon="logo" />
|
||||||
</router-link>
|
</router-link>
|
||||||
<hr>
|
<hr>
|
||||||
<router-link to="/memos" class="nav-item">
|
<router-link to="/memos" class="nav-item p-2">
|
||||||
<svg-vue icon="memos" />
|
<svg-vue icon="memos" />
|
||||||
<span v-bind:class="{ navhidden: !toggleNav }">Memos</span>
|
<span v-bind:class="{ navhidden: !toggleNav }">Memos</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
<router-link to="/jeux" class="nav-item">
|
<router-link to="/jeux" class="nav-item p-2">
|
||||||
<svg-vue icon="games" />
|
<svg-vue icon="games" />
|
||||||
<span v-bind:class="{ navhidden: !toggleNav }">Jeux</span>
|
<span v-bind:class="{ navhidden: !toggleNav }">Jeux</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
<div @click="toggleNavBar" class="nav-toggle mt-5">
|
</div>
|
||||||
|
<div @click="toggleNavBar" class="nav-toggle flex ml-2">
|
||||||
<svg-vue icon="arrow" v-bind:class="{ small: !toggleNav }" />
|
<svg-vue icon="arrow" v-bind:class="{ small: !toggleNav }" />
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative mt-1">
|
<div class="relative mb-2">
|
||||||
<label v-if="label" :for="name" class="pb-1">{{ label }}</label>
|
<label v-if="label" :for="name" class="pb-1">{{ label }}</label>
|
||||||
<textarea :id="name" type="text" v-model="value" :placeholder="placeholder" @input="updateField()" :class="errorClassObject()" class="p-1">{{ data }}</textarea>
|
<textarea :id="name" type="text" v-model="value" :placeholder="placeholder" @input="updateField()" :class="errorClassObject()" class="w-full h-64 rounded p-2">{{ data }}</textarea>
|
||||||
<p class="text-alert m-0" v-text="errorMessage()">Error Here</p>
|
<p class="text-red-600 m-0" v-text="errorMessage()">Error Here</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex-between flex-middle py-1 px-2 topbar">
|
<div class="top-bar flex justify-between bg-orange-300">
|
||||||
<router-link v-if="authUser" :to="'/profile'" class="flex-middle avatar-box">
|
<router-link v-if="authUser" :to="'/profile'" class="flex items-center m-2">
|
||||||
<Avatar :avatar="authUser.data.attributes.avatar" size="small" :alt="authUser.data.attributes.name" class="mr-1"/>
|
<Avatar :avatar="authUser.data.attributes.avatar" size="small" :alt="authUser.data.attributes.name" class="w-10 h-10"/>
|
||||||
{{ authUser.data.attributes.name }}
|
<span class="ml-2 hover:text-orange-900">{{ authUser.data.attributes.name }}</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
<form v-if="authUser && search" class="search-box">
|
<form v-if="authUser && search" class="m-2">
|
||||||
<input type="search" name="search" placeholder="Search">
|
<input type="search" name="search" placeholder="Search">
|
||||||
<button type="submit" value="S">
|
<button type="submit" value="S">
|
||||||
<svg-vue icon="search" />
|
<svg-vue icon="search" />
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
<router-link to="/dashboard" v-if="authUser" class="mr-1">
|
<router-link to="/dashboard" v-if="authUser" class="text-orange-600 hover:text-orange-800">
|
||||||
<svg-vue icon="params" />
|
<svg-vue icon="params" class="w-10 m-2 fill-current" />
|
||||||
</router-link>
|
</router-link>
|
||||||
<router-link v-else to="/login">
|
<router-link v-else to="/login">
|
||||||
Se connecter
|
Se connecter
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="m-2">
|
<div class="p-4">
|
||||||
<div class="flex-between">
|
<div class="flex justify-between">
|
||||||
<h1 class="mb-3">Administration</h1>
|
<h1 class="page-title">Administration</h1>
|
||||||
<a href="#" @click.prevent="logout" class="btn btn-icon">
|
<a href="#" @click.prevent="logout" class="btn">
|
||||||
<svg-vue icon="logout" /> Déconnexion
|
<svg-vue icon="logout" /> Déconnexion
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-4">
|
||||||
<h1>Liste des jeux</h1>
|
<h1 class="page-title">Liste des jeux</h1>
|
||||||
<div class="container-cards-list mt-2">
|
<div class="flex flex-wrap mt-4">
|
||||||
<HangmanIndex link="/jeux/pendu" class="card" />
|
<HangmanIndex link="/jeux/pendu" class="w-full sm:w-1/2 md:w-1/3 lg:w-1/4 card" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2 game-container">
|
<div class="p-2 game-container">
|
||||||
<h1 class="text-center">Pendu</h1>
|
<h1 class="text-3xl text-center text-orange-900 font-bold">Pendu</h1>
|
||||||
<p class="text-center">Trouve le mot du pendu - Saisi les lettres</p>
|
<p class="text-center mb-4">Trouve le mot du pendu - Saisi les lettres</p>
|
||||||
<div class="flex-center dic-select">
|
<div class="flex justify-center dic-select">
|
||||||
<div v-for="(dic, key) in dictionary">
|
<div v-for="(dic, key) in dictionary">
|
||||||
<a v-if="!selectedWord" class="btn-primary mr-1" @click="selectWord">{{ key }}</a>
|
<a v-if="!selectedWord" class="btn-primary mr-1" @click="selectWord">{{ key }}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="memo-edit p-2">
|
<div class="p-4">
|
||||||
<div class="flex-between mb-1">
|
<div class="flex justify-between flex-center mb-4">
|
||||||
<router-link to="/memos/" class="btn">< Back</router-link>
|
<router-link to="/memos/" class="btn">< Back</router-link>
|
||||||
<button @click="$router.back()" class="btn-alert mr-1">Cancel</button>
|
<button @click="$router.back()" class="btn-alert">Cancel</button>
|
||||||
</div>
|
</div>
|
||||||
<form @submit.prevent="submitForm">
|
<form @submit.prevent="submitForm">
|
||||||
<InputField name="name" label="Title" placeholder="Your Title" required @update:field="form.name = $event" :errors="errors" />
|
<InputField name="name" label="Title" placeholder="Your Title" required @update:field="form.name = $event" :errors="errors" />
|
||||||
<TextAreaField class="memo-text-area" name="memo" placeholder="Your Memo" required @update:field="form.memo = $event" :errors="errors" />
|
<TextAreaField class="" name="memo" placeholder="Your Memo" required @update:field="form.memo = $event" :errors="errors" />
|
||||||
|
|
||||||
<div class="flex-end mt-1">
|
<div class="flex justify-end mt-2">
|
||||||
<button class="btn-primary">Add New Memo</button>
|
<button class="btn-primary">Add New Memo</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -12,15 +12,15 @@
|
|||||||
:model="form.type"
|
:model="form.type"
|
||||||
classes="cover"
|
classes="cover"
|
||||||
:alt="form.name"/>
|
:alt="form.name"/>
|
||||||
<div class="flex-between ml-2 mt-1 absolute t-0">
|
|
||||||
<router-link :to="'/memos/' + this.$route.params.id" class="btn-secondary">< Back</router-link>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="p-4">
|
||||||
|
<div class="flex justify-between mb-4">
|
||||||
|
<router-link :to="'/memos/' + this.$route.params.id" class="btn">< Back</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-2">
|
|
||||||
<form @submit.prevent="submitForm">
|
<form @submit.prevent="submitForm">
|
||||||
<InputField name="name" :data="form.name" label="Title" placeholder="Your Title" required @update:field="form.name = $event" :errors="errors" />
|
<InputField name="name" :data="form.name" label="Title" placeholder="Your Title" required @update:field="form.name = $event" :errors="errors" />
|
||||||
<TextAreaField class="memo-text-area" name="memo" :data="form.memo" placeholder="Your Memo" required @update:field="form.memo = $event" :errors="errors" />
|
<TextAreaField class="memo-text-area" name="memo" :data="form.memo" placeholder="Your Memo" required @update:field="form.memo = $event" :errors="errors" />
|
||||||
<div class="flex-end mt-1">
|
<div class="flex justify-end mt-2">
|
||||||
<button class="btn-primary">Save</button>
|
<button class="btn-primary">Save</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-2">
|
<div class="p-4">
|
||||||
<div class="flex-between flex-center mb-1">
|
<div class="flex justify-between flex-center mb-4">
|
||||||
<a href="#" class="btn" @click="$router.back()">< Back</a>
|
<a href="#" class="btn" @click="$router.back()">< Back</a>
|
||||||
<router-link :to="'/memos/create'" class="btn-primary">Add New Memo</router-link>
|
<router-link :to="'/memos/create'" class="btn-primary">Add New Memo</router-link>
|
||||||
</div>
|
</div>
|
||||||
<Loader v-if="loading" />
|
<Loader v-if="loading" />
|
||||||
<div v-else class="container-cards-list">
|
<div v-else class="flex flex-wrap -m-2">
|
||||||
<div v-if="memos.lenght === 0">
|
<div v-if="memos.lenght === 0">
|
||||||
<p>No memos yet. <router-link to="/memos/create">Get Started ></router-link></p>
|
<p>No memos yet. <router-link to="/memos/create">Get Started ></router-link></p>
|
||||||
</div>
|
</div>
|
||||||
<router-link v-for="memo in memos" :key="memo.data.memo_id" :to="'/memos/' + memo.data.memo_id" class="card">
|
<router-link v-for="memo in memos" :key="memo.data.memo_id" :to="'/memos/' + memo.data.memo_id" class="w-full sm:w-1/2 md:w-1/3 lg:w-1/4">
|
||||||
<div>
|
<div class="m-2 max-w-lg rounded overflow-hidden shadow-lg bg-white">
|
||||||
<img :src="memo.data.attributes.cover_image.data.attributes.path" alt="" class="cover">
|
<img :src="memo.data.attributes.cover_image.data.attributes.path" alt="" class="w-full">
|
||||||
<h1 class="p-1">{{ memo.data.name }}</h1>
|
<div class="px-6 py-4">
|
||||||
|
<h1 class="text-gray-700 text-">{{ memo.data.name }}</h1>
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end py-2">
|
||||||
|
<span class="inline-block bg-orange-400 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2">{{ memo.data.last_updated }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="memo-date p-1">{{ memo.data.last_updated }}</div>
|
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,37 +2,36 @@
|
|||||||
<div>
|
<div>
|
||||||
<Loader v-if="loading" />
|
<Loader v-if="loading" />
|
||||||
<div v-else>
|
<div v-else>
|
||||||
|
<div v-if="modal" class="modal-container" @click="modal = ! modal"></div>
|
||||||
|
<div v-if="modal" class="modal">
|
||||||
|
<p class="m-2 text-center">Are you sure you want to delete this record ?</p>
|
||||||
|
<div class="flex justify-center mx-2 my-4">
|
||||||
|
<button class="btn-secondary mr-2" @click="modal = ! modal">Cancel</button>
|
||||||
|
<button class="btn-alert" @click="destroy"> Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<img
|
<img
|
||||||
v-if="!loading"
|
v-if="!loading"
|
||||||
class="cover"
|
class="cover"
|
||||||
:src="memo.attributes.cover_image.data.attributes.path"
|
:src="memo.attributes.cover_image.data.attributes.path"
|
||||||
/>
|
/>
|
||||||
<div class="flex-col flex-between absolute memo-cover">
|
<div class="absolute flex flex-col justify-between w-full top-0 bottom-0">
|
||||||
<div class="flex-between px-2 py-1">
|
<div class="flex items-center justify-between p-4">
|
||||||
<router-link to="/memos/" class="btn-secondary">< Back</router-link>
|
<router-link to="/memos/" class="btn-secondary">< Back</router-link>
|
||||||
<div v-if="modal" class="modal-container" @click="modal = ! modal">
|
|
||||||
<div class="modal">
|
|
||||||
<p class="m-1 text-center">Are you sure you want to delete this record ?</p>
|
|
||||||
<div class="flex-center m-1 mt-2">
|
|
||||||
<button class="btn-secondary mr-2" @click="modal = ! modal">Cancel</button>
|
|
||||||
<button class="btn-alert" @click="destroy"> Delete</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-middle">
|
<div class="flex-middle">
|
||||||
<router-link :to="'/memos/' + memo.memo_id + '/edit'" class="btn-secondary mr-1" >Edit</router-link>
|
<router-link :to="'/memos/' + memo.memo_id + '/edit'" class="btn-secondary mr-1" >Edit</router-link>
|
||||||
<a href="#" class="btn-alert" @click="modal = ! modal">Delete</a>
|
<a href="#" class="btn-alert" @click="modal = ! modal">Delete</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="memo-title flex-center">{{ memo.name }}</h1>
|
<h1 class="flex justify-center text-white text-3xl px-4 font-bold text-shadow">{{ memo.name }}</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <TagBox :memo="memo" />-->
|
<!-- <TagBox :memo="memo" />-->
|
||||||
<div class="p-2">
|
<div class="p-4">
|
||||||
|
|
||||||
<p class="memo-style pt-1" v-html="memoMarkdown"></p>
|
<p class="pt-2" v-html="memoMarkdown"></p>
|
||||||
<div class="memo-change">@last update : {{ memo.last_updated }}</div>
|
<div class="bg-orange-400 rounded mt-2 px-2 py-1 flex justify-end">@last update {{ memo.last_updated }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
:author="authUser"
|
:author="authUser"
|
||||||
:id="authUser.data.user_id"
|
:id="authUser.data.user_id"
|
||||||
:model="authUser.data.type"
|
:model="authUser.data.type"
|
||||||
classes="cover"
|
classes=""
|
||||||
:alt="authUser.data.attributes.name"/>
|
:alt="authUser.data.attributes.name"/>
|
||||||
<div class="absolute b-0">
|
<div class="absolute w-64 bottom-0">
|
||||||
<UploadableImage
|
<UploadableImage
|
||||||
:image-width=750
|
:image-width=750
|
||||||
:image-height=750
|
:image-height=750
|
||||||
@@ -20,9 +20,9 @@
|
|||||||
:author="authUser"
|
:author="authUser"
|
||||||
:id="authUser.data.user_id"
|
:id="authUser.data.user_id"
|
||||||
:model="authUser.data.type"
|
:model="authUser.data.type"
|
||||||
classes="profile absolute"
|
classes="absolute w-64 h-64 -bottom-12 left-8 rounded-full"
|
||||||
:alt="authUser.data.attributes.name"/>
|
:alt="authUser.data.attributes.name"/>
|
||||||
<h1 class="profile-title">{{ authUser.data.attributes.name }}</h1>
|
<h1 class="relative z-10 text-white text-shadow text-3xl left-80 bottom-0">{{ authUser.data.attributes.name }}</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-if="authUser">
|
<div v-if="authUser">
|
||||||
<div class="flex mb-4">
|
<div class="flex m-4">
|
||||||
<div class="avatar mr-2">
|
<div class="avatar mr-2">
|
||||||
<Avatar :avatar="authUser.data.attributes.avatar" size="large" :alt="authUser.data.attributes.name" />
|
<Avatar :avatar="authUser.data.attributes.avatar" size="6xl" :alt="authUser.data.attributes.name" class="w-24 h-24" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-col flex-center">
|
<div class="flex flex-col justify-center ml-2">
|
||||||
<div><strong>{{ authUser.data.attributes.name }}</strong></div>
|
<div><strong>{{ authUser.data.attributes.name }}</strong></div>
|
||||||
<div><strong>{{ authUser.data.attributes.email }}</strong></div>
|
<div><strong>{{ authUser.data.attributes.email }}</strong></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -18,10 +18,10 @@
|
|||||||
<transition name="fade">
|
<transition name="fade">
|
||||||
<form @submit.prevent="addMember" v-if="userAddToggle" class="box-toggle-content" >
|
<form @submit.prevent="addMember" v-if="userAddToggle" class="box-toggle-content" >
|
||||||
<AlertBox v-if="alertType" :type="alertType" :message="alertMessage" class="mb-1" />
|
<AlertBox v-if="alertType" :type="alertType" :message="alertMessage" class="mb-1" />
|
||||||
<div class="flex mb-1">
|
<div class="flex mb-2">
|
||||||
<InputField name="name" label="Nom du nouveau membre" placeholder="Nom" required :errors="errors" @update:field="form.name = $event" class="mr-1" />
|
<InputField name="name" label="Nom du nouveau membre" placeholder="Nom" required :errors="errors" @update:field="form.name = $event" class="mr-1" />
|
||||||
<InputField name="email" type="email" label="Adresse email du nouveau membre" placeholder="E-mail" required :errors="errors" @update:field="form.email = $event" class="mr-1" />
|
<InputField name="email" type="email" label="Adresse email du nouveau membre" placeholder="E-mail" required :errors="errors" @update:field="form.email = $event" class="mr-1" />
|
||||||
<div class="flex-middle mt-4">
|
<div class="flex items-end mb-2">
|
||||||
<button class="btn-primary">Ajouter</button>
|
<button class="btn-primary">Ajouter</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
52
resources/sass/app.scss
vendored
52
resources/sass/app.scss
vendored
@@ -1,30 +1,36 @@
|
|||||||
|
|
||||||
@import "setup/reset";
|
@tailwind base;
|
||||||
@import "setup/colors";
|
@tailwind components;
|
||||||
@import "setup/fonts";
|
|
||||||
@import "setup/positions";
|
|
||||||
@import "setup/containers";
|
|
||||||
@import "setup/effects";
|
|
||||||
|
|
||||||
|
|
||||||
|
//@import "setup/reset";
|
||||||
|
//@import "setup/colors";
|
||||||
|
//@import "setup/fonts";
|
||||||
|
//@import "setup/positions";
|
||||||
|
//@import "setup/containers";
|
||||||
|
//@import "setup/effects";
|
||||||
|
//
|
||||||
@import "components/transitions";
|
@import "components/transitions";
|
||||||
@import "components/btn";
|
@import "components/btn";
|
||||||
@import "components/elements";
|
@import "components/elements";
|
||||||
@import "components/loader";
|
//@import "components/loader";
|
||||||
@import "components/events";
|
//@import "components/main";
|
||||||
@import "components/main";
|
|
||||||
@import "components/nav";
|
@import "components/nav";
|
||||||
@import "components/topbar";
|
//@import "components/topbar";
|
||||||
@import "components/modal";
|
//@import "components/modal";
|
||||||
@import "components/images";
|
//@import "components/images";
|
||||||
@import "components/avatar";
|
//@import "components/avatar";
|
||||||
@import "components/alert_box";
|
//@import "components/alert_box";
|
||||||
@import "components/search_box";
|
//@import "components/search_box";
|
||||||
@import "components/owfont-regular";
|
//@import "components/owfont-regular";
|
||||||
|
//
|
||||||
@import "pages/auth";
|
//@import "pages/auth";
|
||||||
@import "pages/users";
|
//@import "pages/users";
|
||||||
@import "pages/memos";
|
//@import "pages/memos";
|
||||||
@import "pages/meteo";
|
//@import "pages/meteo";
|
||||||
@import "pages/games";
|
//@import "pages/games";
|
||||||
|
//
|
||||||
@import "pages/games/hangman";
|
@import "pages/games/hangman";
|
||||||
|
|
||||||
|
|
||||||
|
@tailwind utilities;
|
||||||
|
|||||||
127
resources/sass/components/_btn.scss
vendored
127
resources/sass/components/_btn.scss
vendored
@@ -1,68 +1,107 @@
|
|||||||
// Button
|
// Button
|
||||||
|
|
||||||
|
//.btn {
|
||||||
|
// font-size: 1.6rem;
|
||||||
|
// border: 1px solid transparent;
|
||||||
|
// padding: 0.5rem 1rem;
|
||||||
|
// border-radius: 0.5rem;
|
||||||
|
// cursor: pointer;
|
||||||
|
// box-shadow: 1px 1px 2px $grey;
|
||||||
|
// text-decoration: none;
|
||||||
|
// transition: background-color 0.2s, color 0.2s;
|
||||||
|
//
|
||||||
|
// &:hover {
|
||||||
|
// transition: background-color 0.2s, color 0.2s;
|
||||||
|
// background-color: $mediumDark;
|
||||||
|
// color: $white;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.btn-primary {
|
||||||
|
// @extend .btn;
|
||||||
|
// background-color: $medium;
|
||||||
|
// border-color: $medium;
|
||||||
|
// color: $white;
|
||||||
|
//
|
||||||
|
// &:visited,
|
||||||
|
// &:focus {
|
||||||
|
// color: $white;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.btn-secondary {
|
||||||
|
// @extend .btn;
|
||||||
|
// background-color: $mediumLight;
|
||||||
|
// border-color: $mediumLight;
|
||||||
|
// color: $dark;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.btn-alert {
|
||||||
|
// @extend .btn;
|
||||||
|
// background-color: $error;
|
||||||
|
// border-color: $error;
|
||||||
|
// color: $white;
|
||||||
|
//
|
||||||
|
// &:hover {
|
||||||
|
// background-color: $dark;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.btn-icon {
|
||||||
|
// @extend .btn;
|
||||||
|
// display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
// height: 4rem;
|
||||||
|
//
|
||||||
|
// &:hover svg {
|
||||||
|
// fill: $white;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// svg {
|
||||||
|
// height: 3rem;
|
||||||
|
// margin-right: 1rem;
|
||||||
|
//
|
||||||
|
// &:hover {
|
||||||
|
// fill: $white;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
font-size: 1.6rem;
|
@apply border bg-orange-400 text-white py-2 px-4 shadow-sm rounded-md;
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
cursor: pointer;
|
|
||||||
box-shadow: 1px 1px 2px $grey;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: background-color 0.2s, color 0.2s;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transition: background-color 0.2s, color 0.2s;
|
@apply text-white bg-orange-600 transition-all duration-300;
|
||||||
background-color: $mediumDark;
|
}
|
||||||
color: $white;
|
|
||||||
|
svg {
|
||||||
|
@apply w-4 fill-current mr-2 inline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
@extend .btn;
|
@extend .btn;
|
||||||
background-color: $medium;
|
@apply bg-orange-600;
|
||||||
border-color: $medium;
|
|
||||||
color: $white;
|
|
||||||
|
|
||||||
&:visited,
|
&:hover {
|
||||||
&:focus {
|
@apply bg-orange-800;
|
||||||
color: $white;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-secondary {
|
.btn-secondary {
|
||||||
@extend .btn;
|
@extend .btn;
|
||||||
background-color: $mediumLight;
|
@apply bg-orange-600;
|
||||||
border-color: $mediumLight;
|
|
||||||
color: $dark;
|
&:hover {
|
||||||
|
@apply bg-orange-800;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-alert {
|
.btn-alert {
|
||||||
@extend .btn;
|
@extend .btn;
|
||||||
background-color: $error;
|
@apply bg-red-600 text-white;
|
||||||
border-color: $error;
|
|
||||||
color: $white;
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $dark;
|
@apply bg-red-800;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-icon {
|
|
||||||
@extend .btn;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 4rem;
|
|
||||||
|
|
||||||
&:hover svg {
|
|
||||||
fill: $white;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
height: 3rem;
|
|
||||||
margin-right: 1rem;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
fill: $white;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
104
resources/sass/components/_elements.scss
vendored
104
resources/sass/components/_elements.scss
vendored
@@ -1,42 +1,94 @@
|
|||||||
// Elements
|
// Elements
|
||||||
|
|
||||||
label {
|
.text-shadow {
|
||||||
display: block;
|
text-shadow: 1px 1px 2px #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea,
|
.left-8 {
|
||||||
input {
|
left: 2rem;
|
||||||
width: 100%;
|
|
||||||
border: 1px solid $light;
|
|
||||||
background-color: $greyLight;
|
|
||||||
font-size: 1.6rem;
|
|
||||||
font-family: $fontMain;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
border-radius: 0.2rem;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
background-color: $white;
|
|
||||||
border-color: $dark;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"] {
|
.left-80 {
|
||||||
width: unset;
|
left: 20rem;
|
||||||
|
|
||||||
& + label {
|
|
||||||
display: inline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.-bottom-12 {
|
||||||
|
bottom: -3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max-h-64 {
|
||||||
|
max-height: 16rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
@apply text-3xl font-bold text-orange-900;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $mediumDark;
|
@apply text-orange-700;
|
||||||
|
|
||||||
&:focus,
|
&:hover {
|
||||||
&:visited {
|
@apply text-orange-900;
|
||||||
color: $dark;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
$modal-duration: 1s;
|
||||||
|
|
||||||
|
.modal-container {
|
||||||
|
@apply top-0 bottom-0 left-0 right-0 fixed bg-black opacity-50 z-10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
@apply bg-white absolute rounded z-20 overflow-hidden shadow max-w-full;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 400px;
|
||||||
|
animation-name: modalopen;
|
||||||
|
animation-duration: $modal-duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box-toggle {
|
||||||
|
@apply shadow;
|
||||||
|
|
||||||
|
&-header {
|
||||||
|
@apply flex justify-between items-center px-4 py-2 rounded bg-orange-400 font-bold cursor-pointer;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
@apply w-8 text-orange-600 fill-current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
transform: rotate(270deg);
|
||||||
|
transition: transform 0.3s;
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
@apply bg-orange-300 rounded;
|
||||||
|
|
||||||
|
svg {
|
||||||
|
@apply max-w-full max-h-64 m-auto fill-current;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
@apply text-2xl text-center font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
@apply bg-orange-500;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
@apply text-orange-700;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
resources/sass/components/_transitions.scss
vendored
10
resources/sass/components/_transitions.scss
vendored
@@ -4,3 +4,13 @@
|
|||||||
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes modalopen {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
25
resources/sass/components/modal.scss
vendored
25
resources/sass/components/modal.scss
vendored
@@ -1,26 +1,25 @@
|
|||||||
$modal-duration: 1s;
|
$modal-duration: 1s;
|
||||||
|
|
||||||
.modal-container {
|
.modal-container {
|
||||||
background-color: rgba(0,0,0,0.6);
|
@apply top-0 bottom-0 left-0 right-0 fixed bg-black opacity-50 z-10;
|
||||||
//display: none;
|
}
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
.modal {
|
.modal {
|
||||||
background-color: #fff;
|
@apply bg-white absolute rounded z-20 overflow-hidden shadow max-w-full;
|
||||||
border-radius: 5px;
|
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
|
||||||
position: absolute;
|
|
||||||
overflow: hidden;
|
|
||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
max-width: 100%;
|
|
||||||
width: 400px;
|
width: 400px;
|
||||||
animation-name: modalopen;
|
animation-name: modalopen;
|
||||||
animation-duration: $modal-duration;
|
animation-duration: $modal-duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes modalopen {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
233
resources/sass/components/nav.scss
vendored
233
resources/sass/components/nav.scss
vendored
@@ -1,103 +1,178 @@
|
|||||||
|
|
||||||
|
//nav {
|
||||||
|
// background-color: $mediumDark;
|
||||||
|
// height: 100vh;
|
||||||
|
// width: 15rem;
|
||||||
|
// flex-shrink: 0;
|
||||||
|
// display: flex;
|
||||||
|
// flex-direction: column;
|
||||||
|
// box-shadow: inset -3px -2px 3px rgba(0,0,0,0.2);
|
||||||
|
// transition: width $transition-delay;
|
||||||
|
//
|
||||||
|
// &.small {
|
||||||
|
// width: 5.5rem;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// hr {
|
||||||
|
// width: 90%;
|
||||||
|
// border-radius: 1px;
|
||||||
|
// border: 1px solid $dark;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// .nav-item {
|
||||||
|
// display: flex;
|
||||||
|
// align-items: center;
|
||||||
|
// text-decoration: none;
|
||||||
|
// color: $light;
|
||||||
|
// padding-top: 1rem;
|
||||||
|
// padding-bottom: 1rem;
|
||||||
|
//
|
||||||
|
// span {
|
||||||
|
// overflow: hidden;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// svg {
|
||||||
|
// margin: 0 1rem;
|
||||||
|
// width: 3rem;
|
||||||
|
// transition: fill 0.2s;
|
||||||
|
// fill: $light;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// &:hover {
|
||||||
|
// color: $dark;
|
||||||
|
// background-color: $light;
|
||||||
|
// transition: color 0.2s, background-color 0.2s;
|
||||||
|
//
|
||||||
|
// svg {
|
||||||
|
// fill: $dark;
|
||||||
|
// transition: fill 0.2s;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// //&:visited {
|
||||||
|
// // color: $dark;
|
||||||
|
// //}
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.site-logo {
|
||||||
|
// width: 3rem;
|
||||||
|
// fill: $light;
|
||||||
|
// transition: fill 0.2s;
|
||||||
|
//
|
||||||
|
// &:hover {
|
||||||
|
// fill: $dark;
|
||||||
|
// transition: fill 0.2s;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.navhidden {
|
||||||
|
// width: 0;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//.site-logo-main {
|
||||||
|
// @extend .site-logo;
|
||||||
|
// display: block;
|
||||||
|
// margin: 1rem;
|
||||||
|
// width: 13rem;
|
||||||
|
// transition: width $transition-delay;
|
||||||
|
//
|
||||||
|
// svg {
|
||||||
|
//
|
||||||
|
// width: 100%;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// &.small {
|
||||||
|
// //padding-bottom: 10rem;
|
||||||
|
// width: 3.5rem;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//.nav-toggle {
|
||||||
|
// @extend .site-logo;
|
||||||
|
// align-self: center;
|
||||||
|
//
|
||||||
|
// svg {
|
||||||
|
// transition: transform $transition-delay;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// svg.small {
|
||||||
|
// transform: rotate(-180deg);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
nav {
|
nav {
|
||||||
background-color: $mediumDark;
|
@apply w-48;
|
||||||
height: 100vh;
|
transition: width 0.3s;
|
||||||
width: 15rem;
|
|
||||||
flex-shrink: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
box-shadow: inset -3px -2px 3px rgba(0,0,0,0.2);
|
|
||||||
transition: width $transition-delay;
|
|
||||||
|
|
||||||
&.small {
|
svg {
|
||||||
width: 5.5rem;
|
@apply fill-current text-orange-600 w-12 p-2;
|
||||||
|
transition: color 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
@apply text-orange-800;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
.logo {
|
||||||
width: 90%;
|
@apply block;
|
||||||
border-radius: 1px;
|
|
||||||
border: 1px solid $dark;
|
svg {
|
||||||
|
@apply w-40 m-2;
|
||||||
|
transition: width 0.3s, color 0.3s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-item {
|
.nav-item {
|
||||||
display: flex;
|
@apply flex items-center;
|
||||||
align-items: center;
|
|
||||||
text-decoration: none;
|
|
||||||
color: $light;
|
|
||||||
padding-top: 1rem;
|
|
||||||
padding-bottom: 1rem;
|
|
||||||
|
|
||||||
span {
|
span {
|
||||||
overflow: hidden;
|
@apply font-bold text-xl ml-2 overflow-hidden;
|
||||||
}
|
transition: width 0.3s;
|
||||||
|
|
||||||
svg {
|
&:hover {
|
||||||
margin: 0 1rem;
|
@apply text-orange-800;
|
||||||
width: 3rem;
|
}
|
||||||
transition: fill 0.2s;
|
|
||||||
fill: $light;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $dark;
|
@apply bg-orange-500;
|
||||||
background-color: $light;
|
|
||||||
transition: color 0.2s, background-color 0.2s;
|
span,
|
||||||
|
svg {
|
||||||
|
@apply text-orange-800;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-toggle svg {
|
||||||
|
transition: transform 0.3s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nav.small {
|
||||||
|
@apply w-16;
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
@apply w-16 p-0;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
fill: $dark;
|
@apply w-16 m-0;
|
||||||
transition: fill 0.2s;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//&:visited {
|
.nav-item span {
|
||||||
// color: $dark;
|
@apply w-0;
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.site-logo {
|
.nav-toggle svg {
|
||||||
width: 3rem;
|
|
||||||
fill: $light;
|
|
||||||
transition: fill 0.2s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
fill: $dark;
|
|
||||||
transition: fill 0.2s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.navhidden {
|
|
||||||
width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.site-logo-main {
|
|
||||||
@extend .site-logo;
|
|
||||||
display: block;
|
|
||||||
margin: 1rem;
|
|
||||||
width: 13rem;
|
|
||||||
transition: width $transition-delay;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.small {
|
|
||||||
//padding-bottom: 10rem;
|
|
||||||
width: 3.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-toggle {
|
|
||||||
@extend .site-logo;
|
|
||||||
align-self: center;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
transition: transform $transition-delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg.small {
|
|
||||||
transform: rotate(-180deg);
|
transform: rotate(-180deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app {
|
||||||
|
//min-width: 100%;
|
||||||
|
width: initial;
|
||||||
|
}
|
||||||
|
|||||||
19
resources/sass/pages/games/hangman.scss
vendored
19
resources/sass/pages/games/hangman.scss
vendored
@@ -17,14 +17,14 @@
|
|||||||
|
|
||||||
.figure-container {
|
.figure-container {
|
||||||
fill: transparent;
|
fill: transparent;
|
||||||
stroke: $mediumDark;
|
stroke: orange;
|
||||||
stroke-width: 4px;
|
stroke-width: 4px;
|
||||||
stroke-linecap: round;
|
stroke-linecap: round;
|
||||||
}
|
}
|
||||||
|
|
||||||
.figure-part {
|
.figure-part {
|
||||||
display: none;
|
display: none;
|
||||||
stroke: $dark;
|
stroke: #7b341e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrong-letters-container {
|
.wrong-letters-container {
|
||||||
@@ -47,13 +47,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.word {
|
.word {
|
||||||
display: flex;
|
@apply flex justify-center items-center;
|
||||||
align-self: center;
|
|
||||||
justify-self: center;
|
|
||||||
bottom: 1rem;
|
bottom: 1rem;
|
||||||
|
|
||||||
.letter {
|
.letter {
|
||||||
border-bottom: 3px solid $medium;
|
border-bottom: 3px solid #c05621;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -69,16 +67,17 @@
|
|||||||
width: calc(100% - 6rem);
|
width: calc(100% - 6rem);
|
||||||
|
|
||||||
.popup {
|
.popup {
|
||||||
background-color: $medium;
|
background-color: #c05621;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
color: $light;
|
color: #fbd38d;
|
||||||
|
min-height: 10rem;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
color: $dark;
|
color: #7b341e;
|
||||||
border: 0;
|
border: 0;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
padding: 12px 20px;
|
padding: 12px 20px;
|
||||||
@@ -96,7 +95,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.notification-container {
|
.notification-container {
|
||||||
background-color: $mediumLight;
|
background-color: #ed8936;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ Route::middleware('auth:api')->group(function () {
|
|||||||
'/users' => 'UserController',
|
'/users' => 'UserController',
|
||||||
'/memos' => 'MemosController',
|
'/memos' => 'MemosController',
|
||||||
'/meteo' => 'MeteoController',
|
'/meteo' => 'MeteoController',
|
||||||
|
'/to-do-lists' => 'ToDoListController',
|
||||||
|
'/to-do-lists/{toDoList}/to-do' => 'ToDoController',
|
||||||
// '/users/{user}/posts' => 'UserPostController',
|
// '/users/{user}/posts' => 'UserPostController',
|
||||||
// '/friend-request' => 'FriendRequestController',
|
// '/friend-request' => 'FriendRequestController',
|
||||||
]);
|
]);
|
||||||
|
|||||||
11
tailwind.config.js
vendored
Normal file
11
tailwind.config.js
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module.exports = {
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
width: {
|
||||||
|
'96': '24rem'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
variants: {},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
@@ -122,7 +122,7 @@ class MemosTest extends TestCase
|
|||||||
|
|
||||||
$response = $this->patch('/api/memos/' . $memo->id, array_merge($this->data(), ['api_token' => $anotherUser->api_token]));
|
$response = $this->patch('/api/memos/' . $memo->id, array_merge($this->data(), ['api_token' => $anotherUser->api_token]));
|
||||||
|
|
||||||
$response->assertStatus(Response::HTTP_FORBIDDEN);
|
$response->assertStatus(403);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
@@ -138,7 +138,7 @@ class MemosTest extends TestCase
|
|||||||
|
|
||||||
$this->assertCount(0, Memo::all());
|
$this->assertCount(0, Memo::all());
|
||||||
|
|
||||||
$response->assertStatus(Response::HTTP_NO_CONTENT);
|
$response->assertStatus(204);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @test */
|
/** @test */
|
||||||
|
|||||||
124
tests/Feature/ToDoItemsTest.php
Normal file
124
tests/Feature/ToDoItemsTest.php
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use App\Models\ToDo;
|
||||||
|
use App\Models\ToDoList;
|
||||||
|
use App\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Foundation\Testing\WithFaker;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class ToDoItemsTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function a_user_can_create_a_to_do_list()
|
||||||
|
{
|
||||||
|
$this->withoutExceptionHandling();
|
||||||
|
$this->actingAs($user = factory(User::class)->create(), 'api');
|
||||||
|
$toDoList = factory(ToDoList::class)->create(['id' => 123, 'user_id' => $user->id]);
|
||||||
|
|
||||||
|
$response = $this->post('/api/to-do-lists/'. $toDoList->id .'/to-do', [
|
||||||
|
'name' => 'Test name to do',
|
||||||
|
])->assertStatus(201);
|
||||||
|
|
||||||
|
$toDo = ToDo::first();
|
||||||
|
|
||||||
|
$this->assertEquals('Test name to do', $toDo->name);
|
||||||
|
$this->assertEquals($toDoList->todos[0], $toDo);
|
||||||
|
$response->assertJson([
|
||||||
|
'data' => [
|
||||||
|
'to_do_id' => $toDo->id,
|
||||||
|
'attributes' => [
|
||||||
|
'data' => [
|
||||||
|
'name' => $toDo->name,
|
||||||
|
'order' => 0,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'links' => [
|
||||||
|
'self' => url('/to-do-lists/'.$toDo->toDoList->id),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function to_do_name_are_required()
|
||||||
|
{
|
||||||
|
$this->actingAs($user = factory(User::class)->create(), 'api');
|
||||||
|
$toDoList = factory(ToDoList::class)->create(['user_id' => $user->id]);
|
||||||
|
$response = $this->post('/api/to-do-lists/'. $toDoList->id .'/to-do', ['name' => '']);
|
||||||
|
|
||||||
|
$response->assertSessionHasErrors('name');
|
||||||
|
$this->assertCount(0, ToDo::all());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function a_to_do_by_to_do_list_can_be_retrieved()
|
||||||
|
{
|
||||||
|
$this->actingAs($user = factory(User::class)->create(), 'api');
|
||||||
|
$toDoList = factory(ToDoList::class)->create(['user_id' => $user->id]);
|
||||||
|
$toDoList->toDos()->create([
|
||||||
|
'name' => 'Test name to do',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = $this->get('/api/to-do-lists/' . $toDoList->id );
|
||||||
|
|
||||||
|
$response->assertJson([
|
||||||
|
'data' => [
|
||||||
|
'to_do_list_id' => $toDoList->id,
|
||||||
|
'attributes' => [
|
||||||
|
'data' => [
|
||||||
|
'name' => $toDoList->name,
|
||||||
|
'last_updated' => $toDoList->updated_at->diffForHumans(),
|
||||||
|
'to_dos' => [
|
||||||
|
'data' => [
|
||||||
|
[
|
||||||
|
'data' => [
|
||||||
|
'to_do_id' => $toDoList->toDos[0]->id,
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'to_dos_count' => 1,
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function a_to_do_can_be_patch()
|
||||||
|
{
|
||||||
|
$this->withoutExceptionHandling();
|
||||||
|
$this->actingAs($user = factory(User::class)->create(), 'api');
|
||||||
|
$toDoList = factory(ToDoList::class)->create(['id' => 123, 'user_id' => $user->id]);
|
||||||
|
$toDoList->toDos()->create([
|
||||||
|
'name' => 'Test name to do',
|
||||||
|
'order' => 10,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$toDoList = $toDoList->fresh();
|
||||||
|
// $toDoList = ToDoList::first();
|
||||||
|
|
||||||
|
$response = $this->patch('/api/to-do-lists/123/to-do/'. $toDoList->toDos[0]->id, [
|
||||||
|
'name' => 'To Do update'
|
||||||
|
])->assertStatus(200)
|
||||||
|
->assertJson([
|
||||||
|
'data' => [
|
||||||
|
'to_do_id' => $toDoList->toDos[0]->id,
|
||||||
|
'attributes' => [
|
||||||
|
'data' => [
|
||||||
|
'name' => 'To Do update',
|
||||||
|
'order' => 10,
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'links' => [
|
||||||
|
'self' => url('/to-do-lists/'. $toDoList->id),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
163
tests/Feature/ToDoListsTest.php
Normal file
163
tests/Feature/ToDoListsTest.php
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use App\Models\ToDoList;
|
||||||
|
use App\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Foundation\Testing\WithFaker;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class ToDoListsTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function a_user_can_create_a_to_do_list()
|
||||||
|
{
|
||||||
|
$this->withoutExceptionHandling();
|
||||||
|
$this->actingAs($user = factory(User::class)->create(), 'api');
|
||||||
|
|
||||||
|
$response = $this->post('/api/to-do-lists/', [
|
||||||
|
'name' => 'Test name to do list'
|
||||||
|
])->assertStatus(201);
|
||||||
|
|
||||||
|
$toDoList = ToDoList::first();
|
||||||
|
|
||||||
|
$this->assertEquals('Test name to do list', $toDoList->name);
|
||||||
|
$response->assertJson([
|
||||||
|
'data' => [
|
||||||
|
'type' => 'to-do-lists',
|
||||||
|
'to_do_list_id' => $toDoList->id,
|
||||||
|
'attributes' => [
|
||||||
|
'data' => [
|
||||||
|
'name' => $toDoList->name,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'links' => [
|
||||||
|
'self' => $toDoList->path(),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function to_do_list_name_are_required()
|
||||||
|
{
|
||||||
|
$this->actingAs($user = factory(\App\User::class)->create(), 'api');
|
||||||
|
$response = $this->post('/api/to-do-lists/', ['name' => '']);
|
||||||
|
|
||||||
|
$response->assertSessionHasErrors('name');
|
||||||
|
$this->assertCount(0, ToDoList::all());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function a_to_do_list_can_be_retrieved()
|
||||||
|
{
|
||||||
|
$this->actingAs($user = factory(User::class)->create(), 'api');
|
||||||
|
$toDoList = factory(ToDoList::class)->create(['user_id' => $user->id]);
|
||||||
|
|
||||||
|
$response = $this->get('/api/to-do-lists/' . $toDoList->id );
|
||||||
|
|
||||||
|
$response->assertJson([
|
||||||
|
'data' => [
|
||||||
|
'to_do_list_id' => $toDoList->id,
|
||||||
|
'attributes' => [
|
||||||
|
'data' => [
|
||||||
|
'name' => $toDoList->name,
|
||||||
|
'last_updated' => $toDoList->updated_at->diffForHumans(),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'links' => [
|
||||||
|
'self' => $toDoList->path(),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function only_owner_to_do_list_can_retrieved_it()
|
||||||
|
{
|
||||||
|
$user = factory(User::class)->create();
|
||||||
|
$toDoList = factory(ToDoList::class)->create(['user_id' => $user->id]);
|
||||||
|
|
||||||
|
$this->actingAs($userAnother = factory(User::class)->create(), 'api');
|
||||||
|
|
||||||
|
$response = $this->get('/api/to-do-lists/' . $toDoList->id );
|
||||||
|
|
||||||
|
$response->assertStatus(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function a_to_do_list_can_be_patch()
|
||||||
|
{
|
||||||
|
$this->actingAs($user = factory(User::class)->create(), 'api');
|
||||||
|
|
||||||
|
$toDoList = factory(ToDoList::class)->create(['user_id' => $user->id]);
|
||||||
|
|
||||||
|
$response = $this->patch('/api/to-do-lists/' . $toDoList->id, [
|
||||||
|
'name' => 'To Do List Update'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$toDoList = $toDoList->fresh();
|
||||||
|
|
||||||
|
$this->assertEquals('To Do List Update', $toDoList->name);
|
||||||
|
|
||||||
|
$response->assertStatus(200);
|
||||||
|
$response->assertJson([
|
||||||
|
'data' => [
|
||||||
|
'to_do_list_id' => $toDoList->id,
|
||||||
|
'attributes' => [
|
||||||
|
'data' => [
|
||||||
|
'name' => 'To Do List Update'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'links' => [
|
||||||
|
'self' => $toDoList->path(),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function only_the_owner_can_patch_the_to_do_list()
|
||||||
|
{
|
||||||
|
$this->actingAs($user = factory(User::class)->create(), 'api');
|
||||||
|
$toDoList = factory(ToDoList::class)->create();
|
||||||
|
|
||||||
|
$anotherUser = factory(User::class)->create();
|
||||||
|
|
||||||
|
$response = $this->patch('/api/to-do-lists/' . $toDoList->id, ['name' => 'Name changed'], ['api_token' => $anotherUser->api_token]);
|
||||||
|
|
||||||
|
$response->assertStatus(403);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function a_to_do_list_can_be_delete()
|
||||||
|
{
|
||||||
|
$this->actingAs($user = factory(User::class)->create(), 'api');
|
||||||
|
|
||||||
|
$toDoList = factory(ToDoList::class)->create(['user_id' => $user->id]);
|
||||||
|
|
||||||
|
$response = $this->delete('/api/to-do-lists/' . $toDoList->id);
|
||||||
|
|
||||||
|
$toDoList = $toDoList->fresh();
|
||||||
|
|
||||||
|
$this->assertCount(0, ToDoList::all());
|
||||||
|
|
||||||
|
$response->assertStatus(204);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function only_the_owner_can_delete_the_to_do_list()
|
||||||
|
{
|
||||||
|
$user = factory(User::class)->create();
|
||||||
|
$toDoList = factory(ToDoList::class)->create();
|
||||||
|
|
||||||
|
$this->actingAs($anotherUser = factory(User::class)->create(), 'api');
|
||||||
|
|
||||||
|
$response = $this->delete('/api/to-do-lists/' . $toDoList->id);
|
||||||
|
|
||||||
|
$response->assertStatus(403);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
webpack.mix.js
vendored
9
webpack.mix.js
vendored
@@ -1,6 +1,13 @@
|
|||||||
const mix = require('laravel-mix');
|
const mix = require('laravel-mix');
|
||||||
|
const tailwindcss = require('tailwindcss')
|
||||||
|
require('laravel-mix-purgecss');
|
||||||
require('laravel-mix-svg-vue');
|
require('laravel-mix-svg-vue');
|
||||||
|
|
||||||
mix.js('resources/js/app.js', 'public/js')
|
mix.js('resources/js/app.js', 'public/js')
|
||||||
.svgVue()
|
.svgVue()
|
||||||
.sass('resources/sass/app.scss', 'public/css');
|
.sass('resources/sass/app.scss', 'public/css')
|
||||||
|
.options({
|
||||||
|
processCssUrls: false,
|
||||||
|
postCss: [ tailwindcss('./tailwind.config.js') ],
|
||||||
|
})
|
||||||
|
.purgeCss();
|
||||||
|
|||||||
Reference in New Issue
Block a user