Compare commits
No commits in common. "develop" and "main" have entirely different histories.
@ -3,7 +3,7 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Habit;
|
use App\Models\Habit;
|
||||||
use App\Models\Entry;
|
use App\Models\HabitEntry;
|
||||||
use Carbon\CarbonPeriod;
|
use Carbon\CarbonPeriod;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ public function index()
|
|||||||
$dates[] = $date->format('Y-m-d');
|
$dates[] = $date->format('Y-m-d');
|
||||||
}
|
}
|
||||||
|
|
||||||
$entries = Habit::where('id', '1')->first()->entries;
|
$entries = Habit::where('id', '1')->first()->habitEntries;
|
||||||
$entriesArr = array();
|
$entriesArr = array();
|
||||||
|
|
||||||
forEach($dates as $date) {
|
forEach($dates as $date) {
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Http\Requests\EntryRequest;
|
|
||||||
use App\Models\Entry;
|
|
||||||
use App\Models\Habit;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class EntryController extends Controller
|
|
||||||
{
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function create(Habit $habit)
|
|
||||||
{
|
|
||||||
return view('entries.create', [
|
|
||||||
'habit' => $habit
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store(EntryRequest $request)
|
|
||||||
{
|
|
||||||
$habit = Habit::find($request->input('habit-id'));
|
|
||||||
|
|
||||||
// If value doesn't exist (checkbox not checked), set it to '0', else '1'.
|
|
||||||
if (is_null($request->input('value'))) {
|
|
||||||
$value = 0;
|
|
||||||
} elseif ($request->input('value') === "ON") {
|
|
||||||
$value = 1;
|
|
||||||
} else {
|
|
||||||
$value = $request->input('value');
|
|
||||||
}
|
|
||||||
|
|
||||||
Entry::create([
|
|
||||||
'habit_id' => $habit->id,
|
|
||||||
'value' => $value,
|
|
||||||
'date' => $request->input('input-date'),
|
|
||||||
'note' => $request->input('note'),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return redirect()->route('habits.show', $habit)->with('success');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function show($id)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function edit($id)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update(Request $request, $id)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
47
app/Http/Controllers/HabitApiController.php
Normal file
47
app/Http/Controllers/HabitApiController.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Resources\HabitResource;
|
||||||
|
use App\Models\Habit;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class HabitApiController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return HabitResource::collection(Habit::all());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'name' => ['required', 'string'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return new HabitResource(Habit::create($validated));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(Habit $habit)
|
||||||
|
{
|
||||||
|
return new HabitResource($habit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, Habit $habit)
|
||||||
|
{
|
||||||
|
$validated = $request->validate([
|
||||||
|
'name' => ['required'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$habit->update($validated);
|
||||||
|
|
||||||
|
return new HabitResource($habit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Habit $habit)
|
||||||
|
{
|
||||||
|
$habit->delete();
|
||||||
|
|
||||||
|
return response()->json();
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,7 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Http\Requests\HabitsRequest;
|
use App\Http\Requests\HabitsRequest;
|
||||||
use App\Models\Category;
|
|
||||||
use App\Models\Habit;
|
use App\Models\Habit;
|
||||||
use App\Models\Tag;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
@ -14,49 +12,18 @@ class HabitController extends Controller
|
|||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
return view('habits.index', [
|
return view('habits.index', [
|
||||||
'habits' => Auth::user()->habits->sortBy('category'),
|
'habits' => Auth::user()->habits
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
$habit = new Habit;
|
return view('habits.create');
|
||||||
|
|
||||||
return view('habits.create', [
|
|
||||||
'habit' => $habit,
|
|
||||||
'update' => 0,
|
|
||||||
'today' => now()->format('Y-m-d')
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(HabitsRequest $request)
|
public function store(HabitsRequest $request)
|
||||||
{
|
{
|
||||||
$validata = $request->safe();
|
dd($request);
|
||||||
|
|
||||||
$habit = new Habit($validata->all());
|
|
||||||
$habit->user_id = $request->user()->id;
|
|
||||||
$habit->save();
|
|
||||||
|
|
||||||
// Category - add if a name is entered
|
|
||||||
if (!is_null($validata->only('category')['category'])) {
|
|
||||||
$category = Category::firstOrCreate(['name' => $validata->only('category')['category']]);
|
|
||||||
$habit->category()->associate($category);
|
|
||||||
$habit->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tags
|
|
||||||
if (!is_null($validata->only('tags')['tags'])) {
|
|
||||||
$tagsArray = explode(', ', $request->only('tags')['tags']);
|
|
||||||
|
|
||||||
foreach ($tagsArray as $tag) {
|
|
||||||
$tag = Tag::firstOrCreate(['name' => $tag], ['habit_id' => $habit->id]);
|
|
||||||
$habit->tags()->attach($tag);
|
|
||||||
//Todo: make sure tag isn't already linked
|
|
||||||
}
|
|
||||||
$habit->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->route('habits.index')->with('status', 'created');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show($id)
|
public function show($id)
|
||||||
@ -65,29 +32,17 @@ public function show($id)
|
|||||||
|
|
||||||
return view('habits.show', [
|
return view('habits.show', [
|
||||||
'habit' => $habit,
|
'habit' => $habit,
|
||||||
'update' => 0,
|
'entries' => $habit->habitEntries->sortByDesc('date')
|
||||||
'entries' => $habit->entries->sortByDesc('date')
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit($id)
|
public function edit($id)
|
||||||
{
|
{
|
||||||
$habit = Habit::find($id);
|
|
||||||
|
|
||||||
return view('habits.edit', [
|
|
||||||
'habit' => $habit,
|
|
||||||
'update' => 1
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(Request $request, $id)
|
public function update(Request $request, $id)
|
||||||
{
|
{
|
||||||
$habit = Habit::find($id);
|
|
||||||
|
|
||||||
$habit->update($request->safe());
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
|
47
app/Http/Controllers/HabitEntryApiController.php
Normal file
47
app/Http/Controllers/HabitEntryApiController.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Http\Resources\HabitEntryResource;
|
||||||
|
use App\Models\HabitEntry;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class HabitEntryApiController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return HabitEntryResource::collection(HabitEntry::all());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
|
||||||
|
]);
|
||||||
|
|
||||||
|
return new HabitEntryResource(HabitEntry::create($request->validated()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(HabitEntry $habitEntry)
|
||||||
|
{
|
||||||
|
return new HabitEntryResource($habitEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, HabitEntry $habitEntry)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
|
||||||
|
]);
|
||||||
|
|
||||||
|
$habitEntry->update($request->validated());
|
||||||
|
|
||||||
|
return new HabitEntryResource($habitEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(HabitEntry $habitEntry)
|
||||||
|
{
|
||||||
|
$habitEntry->delete();
|
||||||
|
|
||||||
|
return response()->json();
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
|
|
||||||
class CategoryRequest extends FormRequest
|
|
||||||
{
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name' => ['required'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
|
|
||||||
class EntryRequest extends FormRequest
|
|
||||||
{
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'habit-id' => ['required', 'exists:habits,id'],
|
|
||||||
'value' => ['nullable'],
|
|
||||||
'input-date' => ['required', 'date'],
|
|
||||||
'note' => ['nullable', 'string'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function authorize(): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
@ -10,19 +10,7 @@ public function rules(): array
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => ['required', 'string'],
|
'name' => ['required', 'string'],
|
||||||
'category' => ['string', 'nullable'],
|
''
|
||||||
'tags' => ['string', 'nullable'],
|
|
||||||
'question' => ['string'],
|
|
||||||
'type' => ['required', 'string'],
|
|
||||||
'value' => ['numeric'],
|
|
||||||
'suffix' => ['string'],
|
|
||||||
'schedule_value' => ['numeric'],
|
|
||||||
'schedule_unit' => [],
|
|
||||||
'schedule_start' => ['date'],
|
|
||||||
'goal_type' => ['required'],
|
|
||||||
'goal_value' => ['numeric'],
|
|
||||||
'goal_unit' => [],
|
|
||||||
'goal_start' => ['date']
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
|
|
||||||
class TagRequest extends FormRequest
|
|
||||||
{
|
|
||||||
public function rules(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name' => ['required'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
/** @mixin \App\Models\Entry */
|
/** @mixin \App\Models\HabitEntry */
|
||||||
class HabitEntryResource extends JsonResource
|
class HabitEntryResource extends JsonResource
|
||||||
{
|
{
|
||||||
public function toArray(Request $request)
|
public function toArray(Request $request)
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
||||||
|
|
||||||
class Category extends Model
|
|
||||||
{
|
|
||||||
use SoftDeletes, HasFactory;
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'name',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function habits(): HasMany {
|
|
||||||
return $this->hasMany(Habit::class);
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
class Habit extends Model
|
class Habit extends Model
|
||||||
@ -15,84 +13,22 @@ class Habit extends Model
|
|||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
'question',
|
|
||||||
'user_id',
|
'user_id',
|
||||||
'type',
|
'type',
|
||||||
'value',
|
'value',
|
||||||
'suffix',
|
'suffix',
|
||||||
'schedule_value',
|
'schedule_value',
|
||||||
'schedule_unit',
|
'schedule_unit',
|
||||||
'schedule_start',
|
|
||||||
'goal_type',
|
'goal_type',
|
||||||
'goal_value',
|
'goal_value',
|
||||||
'goal_unit',
|
'goal_unit'
|
||||||
'goal_start'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public function isDueToday(): bool
|
public function habitEntries(): HasMany {
|
||||||
{
|
return $this->hasMany(HabitEntry::class);
|
||||||
// Goal - none? Not due today.
|
|
||||||
if ($this->goal_type == 'none') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Goal - if present, use its values
|
|
||||||
if ($this->goal_type == 'custom') {
|
|
||||||
$start = $this->goal_start;
|
|
||||||
$unit = $this->goal_unit;
|
|
||||||
$value = $this->goal_value;
|
|
||||||
} else {
|
|
||||||
$start = $this->schedule_start;
|
|
||||||
$unit = $this->schedule_unit;
|
|
||||||
$value = $this->schedule_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count from starting date to today - *should* there be an entry today?
|
|
||||||
$testdate = new Carbon($start);
|
|
||||||
|
|
||||||
while ($testdate->lt(today())) {
|
|
||||||
$testdate = $testdate->add($unit, $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($testdate->eq(today())) {
|
|
||||||
$entries = Entry::whereBelongsTo($this)->get();
|
|
||||||
foreach ($entries as $entry) {
|
|
||||||
if ($entry->date == today()->format('Y-m-d')) {
|
|
||||||
return false; // Entry for today already found; not due
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true; // Test date == today, but no entry found yet
|
|
||||||
}
|
|
||||||
return false; // Test date overshot; isn't due today
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tagsToString(): string {
|
public function user(): BelongsTo {
|
||||||
$output = "";
|
|
||||||
|
|
||||||
foreach($this->tags as $tag) {
|
|
||||||
$output = $output . " " . $tag->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $output;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function entries(): HasMany
|
|
||||||
{
|
|
||||||
return $this->hasMany(Entry::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function user(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tags(): BelongsToMany
|
|
||||||
{
|
|
||||||
return $this->BelongsToMany(Tag::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function category(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Category::class);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,11 @@
|
|||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
|
|
||||||
class Entry extends Model
|
class HabitEntry extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'habit_id',
|
|
||||||
'value',
|
|
||||||
'date',
|
'date',
|
||||||
'note'
|
'note'
|
||||||
];
|
];
|
@ -1,22 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
||||||
|
|
||||||
class Tag extends Model
|
|
||||||
{
|
|
||||||
use SoftDeletes, HasFactory;
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'name',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function habits(): BelongsToMany
|
|
||||||
{
|
|
||||||
return $this->BelongsToMany(Habit::class);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Database\Factories;
|
|
||||||
|
|
||||||
use App\Models\Category;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
|
||||||
|
|
||||||
class CategoryFactory extends Factory
|
|
||||||
{
|
|
||||||
protected $model = Category::class;
|
|
||||||
|
|
||||||
public function definition(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name' => $this->faker->word(),
|
|
||||||
'created_at' => now(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\Models\Entry;
|
use App\Models\HabitEntry;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
class EntryFactory extends Factory
|
class HabitEntryFactory extends Factory
|
||||||
{
|
{
|
||||||
protected $model = Entry::class;
|
protected $model = HabitEntry::class;
|
||||||
|
|
||||||
public function definition()
|
public function definition()
|
||||||
{
|
{
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\Models\Category;
|
|
||||||
use App\Models\Habit;
|
use App\Models\Habit;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
@ -14,9 +13,8 @@ class HabitFactory extends Factory
|
|||||||
public function definition()
|
public function definition()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => $this->faker->word(),
|
'name' => $this->faker->name(),
|
||||||
'user_id' => User::find('1')->first(),
|
'user_id' => User::find('1')->first()
|
||||||
'category_id' => Category::all()->shuffle()->first(),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Database\Factories;
|
|
||||||
|
|
||||||
use App\Models\Tag;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
|
||||||
|
|
||||||
class TagFactory extends Factory
|
|
||||||
{
|
|
||||||
protected $model = Tag::class;
|
|
||||||
|
|
||||||
public function definition(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'name' => $this->faker->word(),
|
|
||||||
'created_at' => now(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration {
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::create('categories', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->string('name');
|
|
||||||
$table->softDeletes();
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('categories');
|
|
||||||
}
|
|
||||||
};
|
|
@ -11,15 +11,12 @@ public function up()
|
|||||||
$table->id();
|
$table->id();
|
||||||
|
|
||||||
$table->foreignId('user_id')->constrained();
|
$table->foreignId('user_id')->constrained();
|
||||||
$table->foreignId('category_id')->nullable()->constrained();
|
|
||||||
$table->string('name')->default("");
|
$table->string('name')->default("");
|
||||||
$table->string('question')->default("");
|
|
||||||
|
|
||||||
// Type
|
// Type
|
||||||
$table->string('type')->default("todo"); // To do, value
|
$table->string('type')->default("todo"); // To do, value
|
||||||
$table->float('value')->nullable(); // Amount of suffix
|
$table->float('value')->nullable(); // Amount of suffix
|
||||||
$table->string('suffix')->nullable(); // Habit action
|
$table->string('suffix')->nullable(); // Habit action
|
||||||
$table->date('schedule_start')->default(now()); // Since when this habit has started
|
|
||||||
|
|
||||||
// Schedule
|
// Schedule
|
||||||
$table->integer('schedule_value')->default("1"); // How many schedule_units?
|
$table->integer('schedule_value')->default("1"); // How many schedule_units?
|
||||||
@ -29,7 +26,6 @@ public function up()
|
|||||||
$table->string('goal_type')->default('none'); // None, schedule, custom
|
$table->string('goal_type')->default('none'); // None, schedule, custom
|
||||||
$table->integer('goal_value')->nullable(); // Every how many goal_units?
|
$table->integer('goal_value')->nullable(); // Every how many goal_units?
|
||||||
$table->string('goal_unit')->nullable(); // Days, weeks, months
|
$table->string('goal_unit')->nullable(); // Days, weeks, months
|
||||||
$table->date('goal_start')->default(now()); // Since when this goal has started
|
|
||||||
|
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
@ -7,14 +7,12 @@
|
|||||||
return new class extends Migration {
|
return new class extends Migration {
|
||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
Schema::create('entries', function (Blueprint $table) {
|
Schema::create('habit_entries', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
|
|
||||||
$table->foreignId('habit_id')->constrained();
|
$table->foreignId('habit_id')->constrained();
|
||||||
|
|
||||||
$table->float('value')->default(0);
|
|
||||||
$table->date('date')->default(now());
|
$table->date('date')->default(now());
|
||||||
$table->string('note')->default("")->nullable();
|
$table->string('note')->default("");
|
||||||
|
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
@ -22,6 +20,6 @@ public function up()
|
|||||||
|
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
Schema::dropIfExists('entries');
|
Schema::dropIfExists('habit_entries');
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -1,22 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration {
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::create('tags', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->string('name');
|
|
||||||
$table->softDeletes();
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('tags');
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration {
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::create('habit_tag', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
|
|
||||||
$table->foreignId('habit_id')->constrained();
|
|
||||||
$table->foreignId('tag_id')->constrained();
|
|
||||||
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('habit_tag');
|
|
||||||
}
|
|
||||||
};
|
|
@ -3,10 +3,8 @@
|
|||||||
namespace Database\Seeders;
|
namespace Database\Seeders;
|
||||||
|
|
||||||
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||||
use App\Models\Category;
|
|
||||||
use App\Models\Habit;
|
use App\Models\Habit;
|
||||||
use App\Models\Entry;
|
use App\Models\HabitEntry;
|
||||||
use App\Models\Tag;
|
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
@ -18,14 +16,6 @@ class DatabaseSeeder extends Seeder
|
|||||||
*/
|
*/
|
||||||
public function run(): void
|
public function run(): void
|
||||||
{
|
{
|
||||||
Category::factory()
|
|
||||||
->count(5)
|
|
||||||
->create();
|
|
||||||
|
|
||||||
Tag::factory()
|
|
||||||
->count(5)
|
|
||||||
->create();
|
|
||||||
|
|
||||||
User::factory()->create([
|
User::factory()->create([
|
||||||
'name' => 'Niisse',
|
'name' => 'Niisse',
|
||||||
'email' => 'nisselommerde@gmail.com',
|
'email' => 'nisselommerde@gmail.com',
|
||||||
@ -35,7 +25,8 @@ public function run(): void
|
|||||||
|
|
||||||
Habit::factory()
|
Habit::factory()
|
||||||
->count(5)
|
->count(5)
|
||||||
->has(Entry::factory()->count(5))
|
->has(HabitEntry::factory()->count(50))
|
||||||
->create();
|
->create();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
|
||||||
{{ $slot }}
|
|
||||||
</div>
|
|
@ -1,9 +0,0 @@
|
|||||||
<div class="py-4">
|
|
||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
|
||||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
|
||||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
|
||||||
{{ $slot }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,5 +0,0 @@
|
|||||||
<x-slot name="header">
|
|
||||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
|
||||||
{{ $slot }}
|
|
||||||
</h2>
|
|
||||||
</x-slot>
|
|
@ -1,7 +0,0 @@
|
|||||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-md sm:rounded-lg ">
|
|
||||||
<div class="p-6 text-gray-900 dark:text-gray-100 h-full">
|
|
||||||
|
|
||||||
{{ $slot }}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -10,47 +10,32 @@
|
|||||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
||||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
<div class="p-6 text-gray-900 dark:text-gray-100">
|
||||||
|
|
||||||
Habits Due Today: <br>
|
|
||||||
@foreach($habits as $habit)
|
|
||||||
@if($habit->isDueToday())
|
|
||||||
- {{$habit->name}} <br>
|
|
||||||
@endif
|
|
||||||
@endforeach
|
|
||||||
<br>
|
|
||||||
|
|
||||||
Habits Done Today: <br>
|
|
||||||
@foreach($habits as $habit)
|
|
||||||
@if($habit->entries()->where('date', today()->format('Y-m-d'))->exists())
|
|
||||||
- {{$habit->name}} <br>
|
|
||||||
@endif
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="py-12">
|
|
||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
|
||||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
|
||||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
|
||||||
|
|
||||||
|
{{-- @foreach($habits as $habit)--}}
|
||||||
|
{{-- @foreach($habit->entries as $entry)--}}
|
||||||
|
{{-- {{ $habit->name }}, {{ $entry->date }}--}}
|
||||||
|
{{-- <br>--}}
|
||||||
|
{{-- @endforeach--}}
|
||||||
|
{{-- @endforeach--}}
|
||||||
|
|
||||||
<canvas id="myChart" height="200px"></canvas>
|
<canvas id="myChart" height="200px"></canvas>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" ></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
var dates = {{ Js::from($dates) }};
|
var dates = {{ Js::from($dates) }};
|
||||||
var entries = {{ Js::from($entries) }};
|
var entries = {{ Js::from($entries) }};
|
||||||
var name = {{ Js::from($habitName) }};
|
var name = {{ Js::from($habitName) }};
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
<x-app-layout>
|
|
||||||
<x-header-h2> Insert Entry for {{$habit->name}}</x-header-h2>
|
|
||||||
|
|
||||||
<div class="max-w-5xl mx-auto sm:px-6 lg:px-8">
|
|
||||||
|
|
||||||
<form action="{{route('entries.store')}}" method="post">
|
|
||||||
@csrf
|
|
||||||
|
|
||||||
<div class="sm:px-6 lg:px-8 grid grid-cols-3 items-stretch sm:gap-6 lg:gap-8 py-4 mx-auto">
|
|
||||||
|
|
||||||
<!-- To Do Type -->
|
|
||||||
@if($habit->type === 'todo')
|
|
||||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
|
||||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
|
||||||
|
|
||||||
<!-- Checkbox -->
|
|
||||||
<div class="flex flex-col gap-y-4 items-stretch">
|
|
||||||
<div>
|
|
||||||
<x-input-label class="text-center" for="is_done">Habit status</x-input-label>
|
|
||||||
</div>
|
|
||||||
<div class="mx-auto">
|
|
||||||
<input type="checkbox"
|
|
||||||
class="rounded w-32 h-32 dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-md
|
|
||||||
focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800 duration-300"
|
|
||||||
name="value" id="value" value="1"
|
|
||||||
onclick="toggleCheckboxText(this)"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div id="done-text" class="text-center text-xl mt-2">
|
|
||||||
Holder
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<!-- Value / Suffix type -->
|
|
||||||
@if($habit->type === 'value')
|
|
||||||
Value
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<!-- Note, Date, Submit -->
|
|
||||||
<div class="col-span-2 bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg h-full">
|
|
||||||
<div class="p-6 text-gray-900 dark:text-gray-100 h-full">
|
|
||||||
|
|
||||||
<div class="grid grid-col content-between h-full">
|
|
||||||
<div>
|
|
||||||
<x-input-label for="note">Note</x-input-label>
|
|
||||||
<textarea name="note" id="note" rows="3" placeholder="Adding a note is optional."
|
|
||||||
class="w-full border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm disabled:opacity-50"></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row justify-between content-end">
|
|
||||||
<div>
|
|
||||||
<x-input-label for="input-date">Date</x-input-label>
|
|
||||||
<x-text-input type="date" name="input-date" value="{{today()->format('Y-m-d')}}"
|
|
||||||
max="{{today()->format('Y-m-d')}}">
|
|
||||||
</x-text-input>
|
|
||||||
</div>
|
|
||||||
<div class="self-end">
|
|
||||||
<input type="hidden" name="habit-id" value="{{$habit->id}}">
|
|
||||||
<x-primary-button class="py-3">Insert entry</x-primary-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var checkboxText = document.getElementById('done-text');
|
|
||||||
|
|
||||||
toggleCheckboxText(document.getElementById('value')); // Run function once to make sure text matches on reload
|
|
||||||
|
|
||||||
function toggleCheckboxText(checkbox) {
|
|
||||||
|
|
||||||
if (checkbox.checked) {
|
|
||||||
checkboxText.innerText = "🎉 Done 🎉";
|
|
||||||
} else {
|
|
||||||
checkboxText.innerText = "Not done";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</x-app-layout>
|
|
||||||
|
|
@ -1,10 +1,148 @@
|
|||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
|
<x-slot name="header">
|
||||||
|
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||||
|
{{ __('create new habit') }}
|
||||||
|
</h2>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
<div class="py-4">
|
<div class="py-12">
|
||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||||
@include('habits.partials.createOrUpdate-form')
|
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-md sm:rounded-lg">
|
||||||
|
|
||||||
|
<div class="p-6 text-gray-900 dark:text-gray-100">
|
||||||
|
<div class="w-1/2">
|
||||||
|
<form action="{{route('habits.store') }}" method="post">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<!-- Name -->
|
||||||
|
<div>
|
||||||
|
<x-input-label for="name" :value="__('Name')"/>
|
||||||
|
<x-text-input id="name" class="block mt-1 w-full" type="text" name="name"
|
||||||
|
placeholder="Habit name" required
|
||||||
|
:value="old('name')" required autofocus autocomplete="name"/>
|
||||||
|
<x-input-error :messages="$errors->get('name')" class="mt-2"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Type -->
|
||||||
|
<div class="mt-6">
|
||||||
|
<x-input-label for="habit_type" value="Habit Type"></x-input-label>
|
||||||
|
<div class="flex items-center mb-1">
|
||||||
|
<!-- Radio button 1 -->
|
||||||
|
<input id="habit-type-1" type="radio" value="todo" name="type"
|
||||||
|
onclick="toggleHabitValueSuffix(true)"
|
||||||
|
class="w-4 h-4 text-blue-600 bg-gray-50 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
||||||
|
<label for="habit-type-1" class="ml-2">Todo / done</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center mb-1">
|
||||||
|
<input id="habit-type-2" type="radio" value="value" name="type"
|
||||||
|
onclick="toggleHabitValueSuffix(false)"
|
||||||
|
class="w-4 h-4 text-blue-600 bg-gray-50 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
||||||
|
<label for="habit-type-2" class="ml-2 ">Value / suffix</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Value / Suffix -->
|
||||||
|
<x-input-label for="value" value="Value and suffix" class="mt-4"
|
||||||
|
id="habit-suffix-label"/>
|
||||||
|
|
||||||
|
<x-text-input id="habit-value-amount" class="inline-block mt-1" type="number"
|
||||||
|
placeholder="Numeric value" min="0"
|
||||||
|
name="value" disabled/>
|
||||||
|
<x-input-error :messages="$errors->get('value')" class="mt-2"/>
|
||||||
|
|
||||||
|
<x-text-input id="habit-suffix-name" class="inline-block mt-1 disabled:opacity-50"
|
||||||
|
type="text" name="suffix" disabled
|
||||||
|
placeholder="Suffix"
|
||||||
|
:value="old('suffix')" required autofocus autocomplete="suffix"/>
|
||||||
|
<x-input-error :messages="$errors->get('suffix')" class="mt-2"/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Schedule -->
|
||||||
|
<div class="mt-6">
|
||||||
|
<x-input-label for="schedule-value" value="Schedule"></x-input-label>
|
||||||
|
<x-text-input id="schedule-value" class="inline-block mt-1" type="number"
|
||||||
|
placeholder="Numeric value" min="0"
|
||||||
|
name="schedule-value"/>
|
||||||
|
|
||||||
|
<select name="schedule-unit" id="schedule-unit"
|
||||||
|
class="inline-block w-1/2 border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm">
|
||||||
|
<option value="day">Days</option>
|
||||||
|
<option value="week">Weeks</option>
|
||||||
|
<option value="month">Months</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Goal -->
|
||||||
|
<div class="mt-6">
|
||||||
|
<x-input-label value="Goal Type"></x-input-label>
|
||||||
|
<div class="text-sm my-3">
|
||||||
|
Adding a goal changes the display mode from the value and suffix to a calculated
|
||||||
|
percentage.
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center mb-1">
|
||||||
|
<input id="goal-type-1" type="radio" value="none" name="goal_type"
|
||||||
|
onclick="toggleGoalSchedule(true)"
|
||||||
|
class="w-4 h-4 text-blue-600 bg-gray-50 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
||||||
|
<label for="goal-type-1" class="ml-2">No goal</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center mb-1">
|
||||||
|
<input id="goal-type-2" type="radio" value="schedule" name="goal_type"
|
||||||
|
checked="checked" onclick="toggleGoalSchedule(true)"
|
||||||
|
class="w-4 h-4 text-blue-600 bg-gray-50 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
||||||
|
<label for="goal-type-2" class="ml-2 ">Same as schedule</label>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center mb-1">
|
||||||
|
<input id="goal-type-3" type="radio" value="custom" name="goal_type"
|
||||||
|
onclick="toggleGoalSchedule(false)"
|
||||||
|
class="w-4 h-4 text-blue-600 bg-gray-50 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
||||||
|
<label for="goal-type-3" class="ml-2 ">Custom schedule</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- goal-schedule -->
|
||||||
|
<div class="mt-6">
|
||||||
|
<x-input-label for="goal-schedule-unit" value="Goal Schedule"></x-input-label>
|
||||||
|
|
||||||
|
<x-text-input id="goal-schedule-amount" class="inline-block mt-1" type="number"
|
||||||
|
placeholder="Numeric value" min="0" disabled
|
||||||
|
name="goal_value"/>
|
||||||
|
|
||||||
|
<select name="goal_unit" id="goal-schedule-unit"
|
||||||
|
disabled
|
||||||
|
class="inline-block w-1/2 border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm disabled:opacity-50">
|
||||||
|
<option value="day">Days</option>
|
||||||
|
<option value="week">Weeks</option>
|
||||||
|
<option value="month">Months</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Priority -->
|
||||||
|
|
||||||
|
<hr class="my-4">
|
||||||
|
<!-- Submit -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<x-primary-button>Create habit</x-primary-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleHabitValueSuffix(value) {
|
||||||
|
document.getElementById('habit-value-amount').disabled = value;
|
||||||
|
document.getElementById('habit-suffix-name').disabled = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleGoalSchedule(value) {
|
||||||
|
document.getElementById('goal-schedule-amount').disabled = value;
|
||||||
|
document.getElementById('goal-schedule-unit').disabled = value;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
<x-app-layout>
|
|
||||||
|
|
||||||
<div class="py-4">
|
|
||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
|
||||||
@include('habits.partials.createOrUpdate-form')
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</x-app-layout>
|
|
@ -10,8 +10,7 @@
|
|||||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
||||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
<div class="p-6 text-gray-900 dark:text-gray-100">
|
||||||
|
|
||||||
<form action="{{route('habits.create')}}"
|
<form action="{{route('habits.create')}}" method="get">
|
||||||
method="get">
|
|
||||||
@csrf
|
@csrf
|
||||||
<x-primary-button>Create Habit</x-primary-button>
|
<x-primary-button>Create Habit</x-primary-button>
|
||||||
</form>
|
</form>
|
||||||
@ -19,27 +18,19 @@
|
|||||||
|
|
||||||
{{-- Table--}}
|
{{-- Table--}}
|
||||||
|
|
||||||
<table class="table-auto text-left text-gray-500 dark:text-gray-400 border shadow">
|
<table class="table-auto text-left text-gray-500 dark:text-gray-400">
|
||||||
<thead class="text-gray-900 bg-gray-100 dark:bg-gray-700 dark:text-gray-200">
|
<thead class="text-gray-900 bg-gray-100 dark:bg-gray-700 dark:text-gray-200">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col"
|
<th scope="col" class="px-4 py-2">
|
||||||
class="px-4 py-2">
|
Habits
|
||||||
Category
|
|
||||||
</th>
|
</th>
|
||||||
<th scope="col"
|
<th scope="col" class="px-6 py-2">
|
||||||
class="px-4 py-2">
|
{{-- Edit--}}
|
||||||
Habit
|
|
||||||
</th>
|
</th>
|
||||||
<th scope="col"
|
<th scope="col" class="px-6 py-2">
|
||||||
class="px-6 py-2">
|
{{-- Delete--}}
|
||||||
Tags
|
|
||||||
</th>
|
</th>
|
||||||
<th scope="col"
|
<th>
|
||||||
class="px-6 py-2">
|
|
||||||
|
|
||||||
</th>
|
|
||||||
<th scope="col"
|
|
||||||
class="px-6 py-2">
|
|
||||||
|
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -47,35 +38,25 @@ class="px-6 py-2">
|
|||||||
<tbody>
|
<tbody>
|
||||||
@foreach($habits as $habit)
|
@foreach($habits as $habit)
|
||||||
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 even:bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600">
|
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 even:bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600">
|
||||||
<td class="text-left px-4 py-2">
|
|
||||||
@if(is_null($habit->category))
|
|
||||||
No Category
|
|
||||||
@else
|
|
||||||
{{$habit->category->name}}
|
|
||||||
@endif
|
|
||||||
</td>
|
|
||||||
<td class="text-left px-4 py-2">
|
<td class="text-left px-4 py-2">
|
||||||
{{$habit->name}}
|
{{$habit->name}}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-left px-4 py-2">
|
|
||||||
@if(sizeof($habit->tags) != 0)
|
|
||||||
@foreach($habit->tags as $tag)
|
|
||||||
{{$tag->name . " "}}
|
|
||||||
@endforeach
|
|
||||||
@endif
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
<form action="{{route('habits.show', $habit)}}"
|
<form action="{{route('habits.show', $habit)}}" method="get">
|
||||||
method="get">
|
|
||||||
@csrf
|
@csrf
|
||||||
<x-secondary-button type="submit">View</x-secondary-button>
|
<x-secondary-button type="submit">View</x-secondary-button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
<form action="{{route('entry_create', $habit)}}"
|
<form action="{{route('habits.edit', $habit)}}" method="get">
|
||||||
method="get">
|
|
||||||
@csrf
|
@csrf
|
||||||
<x-primary-button>Insert</x-primary-button>
|
<x-primary-button>Edit</x-primary-button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
<td class="px-4 py-2">
|
||||||
|
<form action="{{route('habits.destroy', $habit)}}" method="get">
|
||||||
|
@csrf
|
||||||
|
<x-danger-button>Delete</x-danger-button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -87,3 +68,38 @@ class="px-6 py-2">
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
||||||
|
|
||||||
|
{{-- <div class="w-auto inline-block">--}}
|
||||||
|
{{-- <div class="grid grid-cols-3 gap-x-8 gap-y-2">--}}
|
||||||
|
{{-- <div>--}}
|
||||||
|
{{-- <b>Name</b>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- <div>--}}
|
||||||
|
{{-- <b>Edit</b>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- <div>--}}
|
||||||
|
{{-- <b>Remove</b>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- @foreach($habits as $habit)--}}
|
||||||
|
{{-- <div>--}}
|
||||||
|
{{-- {{ $habit->name }} <br>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- <div>--}}
|
||||||
|
{{-- <form action="{{route('habits.edit', $habit)}}" method="get">--}}
|
||||||
|
{{-- @csrf--}}
|
||||||
|
{{-- <x-primary-button>Edit</x-primary-button>--}}
|
||||||
|
{{-- </form>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- <div>--}}
|
||||||
|
{{-- <form action="{{route('habits.destroy', $habit)}}" method="get">--}}
|
||||||
|
{{-- @csrf--}}
|
||||||
|
{{-- <x-danger-button>Delete</x-danger-button>--}}
|
||||||
|
{{-- </form>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- @endforeach--}}
|
||||||
|
|
||||||
|
{{-- </div>--}}
|
||||||
|
{{-- </div>--}}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
<div>
|
|
||||||
<form
|
|
||||||
action="{{$update ? route('habits.update', $habit) : route('habits.store')}}"
|
|
||||||
method="post">
|
|
||||||
@csrf
|
|
||||||
@if ($update)
|
|
||||||
@method('PUT')
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-5">
|
|
||||||
@include('habits.partials.createOrUpdate.general-card')
|
|
||||||
@include('habits.partials.createOrUpdate.type-card')
|
|
||||||
@include('habits.partials.createOrUpdate.goal-card')
|
|
||||||
@include('habits.partials.createOrUpdate.submit-card')
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const habit_suffix = document.getElementById('habit-suffix-name');
|
|
||||||
const goal_amount = document.getElementById('goal-schedule-amount');
|
|
||||||
const goal_unit = document.getElementById('goal-schedule-unit');
|
|
||||||
const goal_start = document.getElementById('goal-start');
|
|
||||||
|
|
||||||
function toggleHabitValueSuffix(value) {
|
|
||||||
habit_suffix.disabled = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleGoalSchedule(value) {
|
|
||||||
goal_amount.disabled = value;
|
|
||||||
goal_unit.disabled = value;
|
|
||||||
goal_start.disabled = value;
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</div>
|
|
@ -1,81 +0,0 @@
|
|||||||
<x-pagecard>
|
|
||||||
|
|
||||||
<!-- Name -->
|
|
||||||
<div>
|
|
||||||
<x-input-label
|
|
||||||
for="name"
|
|
||||||
:value="__('Name')"/>
|
|
||||||
|
|
||||||
<x-text-input
|
|
||||||
id="name"
|
|
||||||
class="block mt-1 w-full"
|
|
||||||
type="text"
|
|
||||||
name="name"
|
|
||||||
placeholder="Swimming"
|
|
||||||
required
|
|
||||||
autofocus
|
|
||||||
autocomplete="name"
|
|
||||||
:value="old('name', $habit->name)"/>
|
|
||||||
|
|
||||||
<x-input-error
|
|
||||||
:messages="$errors->get('name')"
|
|
||||||
class="mt-2"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Question -->
|
|
||||||
<div class="mt-6">
|
|
||||||
<x-input-label
|
|
||||||
for="question"
|
|
||||||
value="Question to ask"/>
|
|
||||||
<x-text-input
|
|
||||||
id="question"
|
|
||||||
class="block mt-1 w-full"
|
|
||||||
type="text"
|
|
||||||
name="question"
|
|
||||||
placeholder="For how long did I swim?"
|
|
||||||
:value="old('question', $habit->question)"
|
|
||||||
autocomplete="question"/>
|
|
||||||
|
|
||||||
<x-input-error
|
|
||||||
:messages="$errors->get('question')"
|
|
||||||
class="mt-2"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Category input -->
|
|
||||||
<div class="mt-6">
|
|
||||||
<x-input-label
|
|
||||||
for="category"
|
|
||||||
value="Category"/>
|
|
||||||
<x-text-input
|
|
||||||
id="category"
|
|
||||||
class="block mt-1 w-full"
|
|
||||||
type="text"
|
|
||||||
name="category"
|
|
||||||
placeholder="Exercise"
|
|
||||||
:value="old('category', isset($habit->category->name) ? $habit->category->name : '' )"
|
|
||||||
autocomplete="category"/>
|
|
||||||
|
|
||||||
<x-input-error
|
|
||||||
:messages="$errors->get('category')"
|
|
||||||
class="mt-2"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- tag input -->
|
|
||||||
<div class="mt-6">
|
|
||||||
<x-input-label
|
|
||||||
for="tag"
|
|
||||||
value="Tags"/>
|
|
||||||
<x-text-input
|
|
||||||
id="tag"
|
|
||||||
class="block mt-1 w-full"
|
|
||||||
type="text"
|
|
||||||
name="tags"
|
|
||||||
placeholder="Exercise, swimming, health"
|
|
||||||
:value="old('tag', $habit->tagsToString())"
|
|
||||||
autocomplete="tag"/>
|
|
||||||
<x-input-error
|
|
||||||
:messages="$errors->get('tag')"
|
|
||||||
class="mt-2"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</x-pagecard>
|
|
@ -1,123 +0,0 @@
|
|||||||
<x-pagecard>
|
|
||||||
<div class="">
|
|
||||||
<x-input-label value="Goal Type"></x-input-label>
|
|
||||||
<div class="text-sm my-2 text-gray-700">
|
|
||||||
Setting a goal will show you how well you're doing, based on the entries made.
|
|
||||||
If you only want to record the frequency of an activity, you don't need to set a
|
|
||||||
goal.
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center mb-1">
|
|
||||||
<input
|
|
||||||
id="goal-type-1"
|
|
||||||
type="radio"
|
|
||||||
value="none"
|
|
||||||
name="goal_type"
|
|
||||||
onclick="toggleGoalSchedule(true)"
|
|
||||||
@if($habit->goal_type === 'none' || !isset($habit->goal_type))
|
|
||||||
checked
|
|
||||||
@endif
|
|
||||||
class="w-4 h-4 text-blue-600 bg-gray-50 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
for="goal-type-1"
|
|
||||||
class="ml-2"
|
|
||||||
>No goal</label>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center mb-1">
|
|
||||||
<input
|
|
||||||
id="goal-type-2"
|
|
||||||
type="radio"
|
|
||||||
value="schedule"
|
|
||||||
name="goal_type"
|
|
||||||
onclick="toggleGoalSchedule(true)"
|
|
||||||
@if($habit->goal_type === 'schedule')
|
|
||||||
checked
|
|
||||||
@endif
|
|
||||||
class="w-4 h-4 text-blue-600 bg-gray-50 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
for="goal-type-2"
|
|
||||||
class="ml-2 "
|
|
||||||
>Same as schedule</label>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center mb-1">
|
|
||||||
<input
|
|
||||||
id="goal-type-3"
|
|
||||||
type="radio"
|
|
||||||
value="custom"
|
|
||||||
name="goal_type"
|
|
||||||
onclick="toggleGoalSchedule(false)"
|
|
||||||
@if($habit->goal_type === 'custom')
|
|
||||||
checked
|
|
||||||
@endif
|
|
||||||
class="w-4 h-4 text-blue-600 bg-gray-50 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
for="goal-type-3"
|
|
||||||
class="ml-2 "
|
|
||||||
>Custom schedule</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr class="mt-4">
|
|
||||||
|
|
||||||
<!-- goal schedule items -->
|
|
||||||
<div class="mt-4">
|
|
||||||
<x-input-label
|
|
||||||
for="goal-schedule-unit"
|
|
||||||
value="Goal Recurrence"
|
|
||||||
/>
|
|
||||||
<div class="inline-block mt-1 pr-1">
|
|
||||||
Every
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<x-text-input
|
|
||||||
id="goal-schedule-amount"
|
|
||||||
class="inline-block mt-1 w-20"
|
|
||||||
type="number"
|
|
||||||
:value="old('goal_value', isset($habit->goal_value) ? $habit->goal_value : '1')"
|
|
||||||
placeholder=""
|
|
||||||
min="1"
|
|
||||||
required
|
|
||||||
name="goal_value"
|
|
||||||
:disabled="!isset($habit->goal_type) || $habit->goal_type !== 'custom' ? true : false"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<x-input-error
|
|
||||||
:messages="$errors->get('goal_value')"
|
|
||||||
class="mt-2"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Select box -->
|
|
||||||
<select
|
|
||||||
name="goal_unit"
|
|
||||||
id="goal-schedule-unit"
|
|
||||||
required
|
|
||||||
@if(!isset($habit->goal_type) || $habit->goal_type !== 'custom')
|
|
||||||
disabled
|
|
||||||
@endif
|
|
||||||
class="inline-block w-fit border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm disabled:opacity-50"
|
|
||||||
>
|
|
||||||
@foreach(['day', 'week', 'month'] as $time_unit)
|
|
||||||
<option
|
|
||||||
value="{{$time_unit}}"
|
|
||||||
@if($habit->goal_unit === $time_unit) selected @endif >{{$time_unit}}s
|
|
||||||
</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<div class="inline-block mt-1 px-1">
|
|
||||||
starting
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- goal date input -->
|
|
||||||
<x-text-input
|
|
||||||
type="date"
|
|
||||||
name="goal_start"
|
|
||||||
class="inline-block mt-1"
|
|
||||||
id="goal-start"
|
|
||||||
:value="old('goal_start', isset($habit->goal_start) ? $habit->goal_start : $today)"
|
|
||||||
:disabled="!isset($habit->goal_type) || $habit->goal_type !== 'custom' ? true : false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</x-pagecard>
|
|
@ -1,22 +0,0 @@
|
|||||||
<x-pagecard>
|
|
||||||
<div class="w-full h-full">
|
|
||||||
<div class="grid grid-row gap-10 h-full content-center">
|
|
||||||
<div class="text-7xl text-center">
|
|
||||||
🚀🌌
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<hr>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center">
|
|
||||||
<x-primary-button class="px-20 py-4 shadow-md">
|
|
||||||
@if(isset($habit))
|
|
||||||
Save Changes
|
|
||||||
@else
|
|
||||||
Create Habit
|
|
||||||
@endif
|
|
||||||
</x-primary-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</x-pagecard>
|
|
@ -1,129 +0,0 @@
|
|||||||
<x-pagecard>
|
|
||||||
|
|
||||||
<!-- Type -->
|
|
||||||
<div class="">
|
|
||||||
<x-input-label
|
|
||||||
for="habit_type"
|
|
||||||
value="Habit Type"
|
|
||||||
></x-input-label>
|
|
||||||
<div class="flex items-center mb-1 mt-1">
|
|
||||||
|
|
||||||
<!-- Radio button: do-->
|
|
||||||
<input
|
|
||||||
id="habit-type-1"
|
|
||||||
type="radio"
|
|
||||||
value="todo"
|
|
||||||
name="type"
|
|
||||||
onclick="toggleHabitValueSuffix(true)"
|
|
||||||
@if($habit->type === 'todo' || !isset($habit->type)) checked
|
|
||||||
@endif
|
|
||||||
class="w-4 h-4 text-blue-600 bg-gray-50 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
|
||||||
>
|
|
||||||
<label
|
|
||||||
for="habit-type-1"
|
|
||||||
class="ml-2"
|
|
||||||
>To do</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Radio button: value-->
|
|
||||||
<div class="flex items-center mb-1">
|
|
||||||
|
|
||||||
<input
|
|
||||||
id="habit-type-2"
|
|
||||||
type="radio"
|
|
||||||
value="value"
|
|
||||||
name="type"
|
|
||||||
onclick="toggleHabitValueSuffix(false)"
|
|
||||||
@if($habit->type === 'value') checked
|
|
||||||
@endif
|
|
||||||
class="w-4 h-4 text-blue-600 bg-gray-50 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
|
|
||||||
>
|
|
||||||
|
|
||||||
<label
|
|
||||||
for="habit-type-2"
|
|
||||||
class="ml-2 "
|
|
||||||
>Amount and suffix</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Suffix -->
|
|
||||||
<x-input-label
|
|
||||||
class="mt-4"
|
|
||||||
for="value"
|
|
||||||
id="habit-suffix-label"
|
|
||||||
value="Suffix"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<x-text-input
|
|
||||||
:disabled="!isset($habit->type) || $habit->type === 'todo' ? true : false"
|
|
||||||
:value="old('suffix', isset($habit->suffix) ? $habit->suffix : '')"
|
|
||||||
autocomplete="suffix"
|
|
||||||
class="inline-block mt-1 disabled:opacity-50 w-1/2"
|
|
||||||
id="habit-suffix-name"
|
|
||||||
placeholder="minutes"
|
|
||||||
type="text"
|
|
||||||
name="suffix"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<x-input-error
|
|
||||||
:messages="$errors->get('suffix')"
|
|
||||||
class="mt-2"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr class="my-5">
|
|
||||||
|
|
||||||
<!-- Schedule -->
|
|
||||||
<div class="">
|
|
||||||
<x-input-label
|
|
||||||
for="schedule-value"
|
|
||||||
value="Schedule Recurrence"
|
|
||||||
/>
|
|
||||||
<div class="text-sm my-1 text-gray-700">
|
|
||||||
The recurrence value determines how often you will be inquired about this habit.
|
|
||||||
Note: this is different from setting a goal. Set to 0 to disable inquiries.
|
|
||||||
</div>
|
|
||||||
<div class="inline-block mt-4 pr-1">
|
|
||||||
Every
|
|
||||||
</div>
|
|
||||||
<x-text-input
|
|
||||||
id="schedule-value"
|
|
||||||
class="inline-block mt-1 w-20"
|
|
||||||
type="number"
|
|
||||||
placeholder=""
|
|
||||||
min="0"
|
|
||||||
name="schedule_value"
|
|
||||||
:value="old('schedule_value', isset($habit->schedule_value) ? $habit->schedule_value : '1')"
|
|
||||||
/>
|
|
||||||
<x-input-error
|
|
||||||
:messages="$errors->get('schedule_value')"
|
|
||||||
class="mt-2"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<select
|
|
||||||
name="schedule_unit"
|
|
||||||
id="schedule-unit"
|
|
||||||
class="inline-block w-fit border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm"
|
|
||||||
>
|
|
||||||
|
|
||||||
@foreach(['day', 'week', 'month'] as $time_unit)
|
|
||||||
<option
|
|
||||||
value="{{$time_unit}}"
|
|
||||||
@if($habit->schedule_unit === $time_unit) selected @endif >{{$time_unit}}s
|
|
||||||
</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<div class="inline-block mt-1 px-1">
|
|
||||||
starting
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<x-text-input
|
|
||||||
type="date"
|
|
||||||
class="inline-block mt-1"
|
|
||||||
name="schedule_start"
|
|
||||||
id="schedule_start"
|
|
||||||
:value="old('schedule_start', isset($habit->schedule_start) ? $habit->schedule_start : $today)"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</x-pagecard>
|
|
@ -9,12 +9,7 @@
|
|||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-md sm:rounded-lg">
|
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-md sm:rounded-lg">
|
||||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
<div class="p-6 text-gray-900 dark:text-gray-100">
|
||||||
{{ $habit->name }} <br> <br>
|
{{ $habit->name }}
|
||||||
|
|
||||||
<form action="{{route("habits.edit", $habit)}}"
|
|
||||||
method="get">
|
|
||||||
<x-primary-button>Edit</x-primary-button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -23,20 +18,13 @@
|
|||||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-md sm:rounded-lg">
|
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-md sm:rounded-lg">
|
||||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
<div class="p-6 text-gray-900 dark:text-gray-100">
|
||||||
|
<table class="table-auto text-left text-gray-700 dark:text-gray-400">
|
||||||
<table class="table-auto text-left text-gray-700 dark:text-gray-400 border shadow rounded">
|
|
||||||
<thead class="text-gray-900 bg-gray-100 dark:bg-gray-700 dark:text-gray-200">
|
<thead class="text-gray-900 bg-gray-100 dark:bg-gray-700 dark:text-gray-200">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col"
|
<th scope="col" class="px-4 py-2">
|
||||||
class="px-4 py-2">
|
|
||||||
Value
|
|
||||||
</th>
|
|
||||||
<th scope="col"
|
|
||||||
class="px-4 py-2">
|
|
||||||
Date
|
Date
|
||||||
</th>
|
</th>
|
||||||
<th scope="col"
|
<th scope="col" class="px-6 py-2">
|
||||||
class="px-6 py-2">
|
|
||||||
Note
|
Note
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -44,31 +32,6 @@ class="px-6 py-2">
|
|||||||
<tbody>
|
<tbody>
|
||||||
@foreach($entries as $entry)
|
@foreach($entries as $entry)
|
||||||
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 even:bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600">
|
<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700 even:bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600">
|
||||||
<td class="px-4 py-2">
|
|
||||||
@if($habit->type === 'todo')
|
|
||||||
<div class="mx-auto text-center">
|
|
||||||
@if($entry->value == 0)
|
|
||||||
<input type="checkbox"
|
|
||||||
name=""
|
|
||||||
id=""
|
|
||||||
disabled
|
|
||||||
class="rounded w-6 h-6 dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm
|
|
||||||
focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800 duration-300">
|
|
||||||
@else
|
|
||||||
<input type="checkbox"
|
|
||||||
name=""
|
|
||||||
id=""
|
|
||||||
disabled
|
|
||||||
checked
|
|
||||||
class="rounded w-6 h-6 dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm
|
|
||||||
focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800 duration-300">
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
{{$entry->value . $habit->suffix}}
|
|
||||||
@endif
|
|
||||||
|
|
||||||
</td>
|
|
||||||
<td class="text-left px-4 py-2">
|
<td class="text-left px-4 py-2">
|
||||||
{{$entry->date}}
|
{{$entry->date}}
|
||||||
</td>
|
</td>
|
||||||
|
@ -19,13 +19,13 @@
|
|||||||
@include('layouts.navigation')
|
@include('layouts.navigation')
|
||||||
|
|
||||||
<!-- Page Heading -->
|
<!-- Page Heading -->
|
||||||
{{-- @if (isset($header))--}}
|
@if (isset($header))
|
||||||
{{-- <header class="bg-white dark:bg-gray-800 shadow">--}}
|
<header class="bg-white dark:bg-gray-800 shadow">
|
||||||
{{-- <div class="max-w-7xl mx-auto py-6 mb-2 px-4 sm:px-6 lg:px-8">--}}
|
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||||
{{-- {{ $header }}--}}
|
{{ $header }}
|
||||||
{{-- </div>--}}
|
</div>
|
||||||
{{-- </header>--}}
|
</header>
|
||||||
{{-- @endif--}}
|
@endif
|
||||||
|
|
||||||
<!-- Page Content -->
|
<!-- Page Content -->
|
||||||
<main>
|
<main>
|
||||||
|
@ -1,27 +1,24 @@
|
|||||||
<nav x-data="{ open: false }"
|
<nav x-data="{ open: false }" class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700">
|
||||||
class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700 shadow">
|
|
||||||
<!-- Primary Navigation Menu -->
|
<!-- Primary Navigation Menu -->
|
||||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div class="flex justify-between h-12">
|
<div class="flex justify-between h-16">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
{{-- <div class="shrink-0 flex items-center">--}}
|
<div class="shrink-0 flex items-center">
|
||||||
{{-- <a href="{{ route('dashboard') }}">--}}
|
<a href="{{ route('dashboard') }}">
|
||||||
{{-- <x-application-logo class="block h-9 w-auto fill-current text-gray-800 dark:text-gray-200" />--}}
|
<x-application-logo class="block h-9 w-auto fill-current text-gray-800 dark:text-gray-200" />
|
||||||
{{-- </a>--}}
|
</a>
|
||||||
{{-- </div>--}}
|
</div>
|
||||||
|
|
||||||
<!-- Navigation Links -->
|
<!-- Navigation Links -->
|
||||||
<div class="hidden space-x-6 sm:-my-px sm:ml-10 sm:flex">
|
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
|
||||||
<x-nav-link :href="route('dashboard')"
|
<x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
|
||||||
:active="request()->routeIs('dashboard')">
|
|
||||||
{{ __('Dashboard') }}
|
{{ __('Dashboard') }}
|
||||||
</x-nav-link>
|
</x-nav-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hidden space-x-6 sm:-my-px sm:ml-10 sm:flex">
|
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
|
||||||
<x-nav-link :href="route('habits.index')"
|
<x-nav-link :href="route('habits.index')" :active="request()->routeIs('habits.*')">
|
||||||
:active="request()->routeIs('habits.*')">
|
|
||||||
{{ __('Habits') }}
|
{{ __('Habits') }}
|
||||||
</x-nav-link>
|
</x-nav-link>
|
||||||
</div>
|
</div>
|
||||||
@ -29,19 +26,14 @@ class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700 s
|
|||||||
|
|
||||||
<!-- Settings Dropdown -->
|
<!-- Settings Dropdown -->
|
||||||
<div class="hidden sm:flex sm:items-center sm:ml-6">
|
<div class="hidden sm:flex sm:items-center sm:ml-6">
|
||||||
<x-dropdown align="right"
|
<x-dropdown align="right" width="48">
|
||||||
width="48">
|
|
||||||
<x-slot name="trigger">
|
<x-slot name="trigger">
|
||||||
<button class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
|
<button class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
|
||||||
<div>{{ Auth::user()->name }}</div>
|
<div>{{ Auth::user()->name }}</div>
|
||||||
|
|
||||||
<div class="ml-1">
|
<div class="ml-1">
|
||||||
<svg class="fill-current h-4 w-4"
|
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||||
viewBox="0 0 20 20">
|
|
||||||
<path fill-rule="evenodd"
|
|
||||||
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
|
||||||
clip-rule="evenodd"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
@ -53,12 +45,11 @@ class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700 s
|
|||||||
</x-dropdown-link>
|
</x-dropdown-link>
|
||||||
|
|
||||||
<!-- Authentication -->
|
<!-- Authentication -->
|
||||||
<form method="POST"
|
<form method="POST" action="{{ route('logout') }}">
|
||||||
action="{{ route('logout') }}">
|
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<x-dropdown-link :href="route('logout')"
|
<x-dropdown-link :href="route('logout')"
|
||||||
onclick="event.preventDefault();
|
onclick="event.preventDefault();
|
||||||
this.closest('form').submit();">
|
this.closest('form').submit();">
|
||||||
{{ __('Log Out') }}
|
{{ __('Log Out') }}
|
||||||
</x-dropdown-link>
|
</x-dropdown-link>
|
||||||
@ -69,24 +60,10 @@ class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700 s
|
|||||||
|
|
||||||
<!-- Hamburger -->
|
<!-- Hamburger -->
|
||||||
<div class="-mr-2 flex items-center sm:hidden">
|
<div class="-mr-2 flex items-center sm:hidden">
|
||||||
<button @click="open = ! open"
|
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400 transition duration-150 ease-in-out">
|
||||||
class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400 transition duration-150 ease-in-out">
|
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||||
<svg class="h-6 w-6"
|
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||||
stroke="currentColor"
|
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24">
|
|
||||||
<path :class="{'hidden': open, 'inline-flex': ! open }"
|
|
||||||
class="inline-flex"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M4 6h16M4 12h16M4 18h16"/>
|
|
||||||
<path :class="{'hidden': ! open, 'inline-flex': open }"
|
|
||||||
class="hidden"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M6 18L18 6M6 6l12 12"/>
|
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -94,11 +71,9 @@ class="hidden"
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Responsive Navigation Menu -->
|
<!-- Responsive Navigation Menu -->
|
||||||
<div :class="{'block': open, 'hidden': ! open}"
|
<div :class="{'block': open, 'hidden': ! open}" class="hidden sm:hidden">
|
||||||
class="hidden sm:hidden">
|
|
||||||
<div class="pt-2 pb-3 space-y-1">
|
<div class="pt-2 pb-3 space-y-1">
|
||||||
<x-responsive-nav-link :href="route('dashboard')"
|
<x-responsive-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
|
||||||
:active="request()->routeIs('dashboard')">
|
|
||||||
{{ __('Dashboard') }}
|
{{ __('Dashboard') }}
|
||||||
</x-responsive-nav-link>
|
</x-responsive-nav-link>
|
||||||
</div>
|
</div>
|
||||||
@ -116,12 +91,11 @@ class="hidden sm:hidden">
|
|||||||
</x-responsive-nav-link>
|
</x-responsive-nav-link>
|
||||||
|
|
||||||
<!-- Authentication -->
|
<!-- Authentication -->
|
||||||
<form method="POST"
|
<form method="POST" action="{{ route('logout') }}">
|
||||||
action="{{ route('logout') }}">
|
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<x-responsive-nav-link :href="route('logout')"
|
<x-responsive-nav-link :href="route('logout')"
|
||||||
onclick="event.preventDefault();
|
onclick="event.preventDefault();
|
||||||
this.closest('form').submit();">
|
this.closest('form').submit();">
|
||||||
{{ __('Log Out') }}
|
{{ __('Log Out') }}
|
||||||
</x-responsive-nav-link>
|
</x-responsive-nav-link>
|
||||||
|
@ -16,6 +16,9 @@
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Route::apiResource('habits', HabitApiController::class);
|
||||||
|
Route::apiResource('habit-entries', HabitEntryApiController::class);
|
||||||
|
|
||||||
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
||||||
return $request->user();
|
return $request->user();
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use App\Http\Controllers\DashboardController;
|
use App\Http\Controllers\DashboardController;
|
||||||
use App\Http\Controllers\EntryController;
|
|
||||||
use App\Http\Controllers\HabitController;
|
use App\Http\Controllers\HabitController;
|
||||||
use App\Http\Controllers\ProfileController;
|
use App\Http\Controllers\ProfileController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
@ -31,8 +30,4 @@
|
|||||||
|
|
||||||
Route::resource('/habits', HabitController::class);
|
Route::resource('/habits', HabitController::class);
|
||||||
|
|
||||||
Route::resource('/habits/entries', EntryController::class);
|
require __DIR__.'/auth.php';
|
||||||
Route::get('/habits/entries/create/{habit}', [EntryController::class, 'create'])
|
|
||||||
->name('entry_create');
|
|
||||||
|
|
||||||
require __DIR__ . '/auth.php';
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user