Compare commits
No commits in common. "b1ee0f3f18c043f8b3ca9aac81ee912975b3439e" and "28d98f77226481d2891c18ec7bf3b7452f067fd9" have entirely different histories.
b1ee0f3f18
...
28d98f7722
@ -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,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\Habit;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class EntryController extends Controller
|
|
||||||
{
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function createWithHabit(Request $request) {
|
|
||||||
return view('entries.create', [
|
|
||||||
'habit' => Habit::find($request->input('habit'))
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
return view('entries.create', [
|
|
||||||
'habit'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($request)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
||||||
|
}
|
||||||
|
}
|
@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
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,54 +11,21 @@ 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()
|
||||||
{
|
{
|
||||||
return view('habits.create', [
|
return view('habits.create');
|
||||||
'today' => now()->format('Y-m-d')
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(HabitsRequest $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$validata = $request->safe();
|
|
||||||
|
|
||||||
$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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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()->sync($tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->route('habits.index')->with('status', 'created');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
$habit = Habit::find($id);
|
|
||||||
|
|
||||||
return view('habits.show', [
|
|
||||||
'habit' => $habit,
|
|
||||||
'entries' => $habit->entries->sortByDesc('date')
|
|
||||||
]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit($id)
|
public function edit($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'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,19 +9,7 @@ class HabitsRequest extends FormRequest
|
|||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => ['required', 'string'],
|
'name' => ['required'],
|
||||||
'category' => ['string', 'nullable'],
|
|
||||||
'tags' => ['string', 'nullable'],
|
|
||||||
'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,73 +13,14 @@ class Habit extends Model
|
|||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name',
|
'name',
|
||||||
'user_id',
|
'user_id'
|
||||||
'type',
|
|
||||||
'value',
|
|
||||||
'suffix',
|
|
||||||
'schedule_value',
|
|
||||||
'schedule_unit',
|
|
||||||
'schedule_start',
|
|
||||||
'goal_type',
|
|
||||||
'goal_value',
|
|
||||||
'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 entries(): HasMany
|
public function user(): BelongsTo {
|
||||||
{
|
|
||||||
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,12 @@
|
|||||||
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 = [
|
||||||
'date',
|
'date'
|
||||||
'note'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
public function habit(): BelongsTo
|
public function habit(): BelongsTo
|
@ -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(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Database\Factories;
|
|
||||||
|
|
||||||
use App\Models\Entry;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
|
||||||
|
|
||||||
class EntryFactory extends Factory
|
|
||||||
{
|
|
||||||
protected $model = Entry::class;
|
|
||||||
|
|
||||||
public function definition()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'date' => $this->faker->dateTimeThisYear(),
|
|
||||||
'note' => $this->faker->sentence
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
18
database/factories/HabitEntryFactory.php
Normal file
18
database/factories/HabitEntryFactory.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\HabitEntry;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
class HabitEntryFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = HabitEntry::class;
|
||||||
|
|
||||||
|
public function definition()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'date' => $this->faker->dateTimeThisYear()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -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,25 +11,8 @@ 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("");
|
||||||
|
|
||||||
// Type
|
|
||||||
$table->string('type')->default("todo"); // To do, value
|
|
||||||
$table->float('value')->nullable(); // Amount of suffix
|
|
||||||
$table->string('suffix')->nullable(); // Habit action
|
|
||||||
$table->date('schedule_start')->default(now()); // Since when this habit has started
|
|
||||||
|
|
||||||
// Schedule
|
|
||||||
$table->integer('schedule_value')->default("1"); // How many schedule_units?
|
|
||||||
$table->string('schedule_unit')->default("day"); // Days, weeks, months
|
|
||||||
|
|
||||||
// Goal
|
|
||||||
$table->string('goal_type')->default('none'); // None, schedule, custom
|
|
||||||
$table->integer('goal_value')->nullable(); // Every how many goal_units?
|
|
||||||
$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,12 +7,11 @@
|
|||||||
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->date('date')->default(now());
|
$table->date('date');
|
||||||
$table->string('note')->default("");
|
|
||||||
|
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
@ -20,6 +19,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(10)
|
|
||||||
->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(50))
|
->has(HabitEntry::factory()->count(70))
|
||||||
->create();
|
->create();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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">
|
|
||||||
|
|
||||||
{{ $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,19 +0,0 @@
|
|||||||
<x-app-layout>
|
|
||||||
<x-slot name="header">
|
|
||||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
|
||||||
{{ __('Habits') }}
|
|
||||||
</h2>
|
|
||||||
</x-slot>
|
|
||||||
|
|
||||||
<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">
|
|
||||||
|
|
||||||
{{$habit->name}}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</x-app-layout>
|
|
@ -1,186 +1,128 @@
|
|||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
<x-slot name="header">
|
<x-slot name="header">
|
||||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
||||||
Create new habit
|
{{ __('Create New Habit') }}
|
||||||
</h2>
|
</h2>
|
||||||
</x-slot>
|
</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">
|
||||||
|
<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">
|
||||||
|
|
||||||
<form action="{{route('habits.store') }}" method="post">
|
<div class="w-1/2">
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-5">
|
<form action="{{route('habits.store') }}" method="post">
|
||||||
@csrf
|
|
||||||
<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="Habit name" required
|
|
||||||
:value="old('name')" required autofocus autocomplete="name"/>
|
|
||||||
<x-input-error :messages="$errors->get('name')" class="mt-2"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Category input -->
|
<!-- Name -->
|
||||||
<div class="mt-6">
|
<div>
|
||||||
<x-input-label for="category" value="Category"/>
|
<x-input-label for="name" :value="__('Name')"/>
|
||||||
<x-text-input id="category" class="block mt-1 w-full" type="text" name="category"
|
<x-text-input id="name" class="block mt-1 w-full" type="text" name="name"
|
||||||
placeholder="Category name"
|
placeholder="Habit name" required
|
||||||
:value="old('category')" autocomplete="category"/>
|
:value="old('name')" required autofocus autocomplete="name"/>
|
||||||
<x-input-error :messages="$errors->get('category')" class="mt-2"/>
|
<x-input-error :messages="$errors->get('name')" 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="First tag, second tag, guten tag..."
|
|
||||||
:value="old('tag')" autocomplete="tag"/>
|
|
||||||
<x-input-error :messages="$errors->get('tag')" class="mt-2"/>
|
|
||||||
</div>
|
|
||||||
</x-pagecard>
|
|
||||||
|
|
||||||
<x-pagecard>
|
|
||||||
|
|
||||||
<!-- Type -->
|
|
||||||
<div class="">
|
|
||||||
<x-input-label for="habit_type" value="Habit Type"></x-input-label>
|
|
||||||
<div class="flex items-center mb-1">
|
|
||||||
|
|
||||||
<!-- Radio button: todo-->
|
|
||||||
<input id="habit-type-1" type="radio" value="todo" name="type"
|
|
||||||
onclick="toggleHabitValueSuffix(true)" checked
|
|
||||||
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>
|
||||||
|
|
||||||
<!-- Radio button: value-->
|
<!-- Type -->
|
||||||
<div class="flex items-center mb-1">
|
<div class="mt-6">
|
||||||
<input id="habit-type-2" type="radio" value="value" name="type"
|
<x-input-label value="Habit Type"></x-input-label>
|
||||||
onclick="toggleHabitValueSuffix(false)"
|
<div class="flex items-center mb-1">
|
||||||
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">
|
<!-- Radio button 1 -->
|
||||||
<label for="habit-type-2" class="ml-2 ">Value / suffix</label>
|
<input id="habit-type-1" type="radio" value="todo" name="habit-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="habit-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="suffix" 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="habit-value-amount" disabled/>
|
||||||
|
|
||||||
|
<x-text-input id="habit-suffix-name" class="inline-block mt-1 disabled:opacity-50"
|
||||||
|
type="text" name="habit-suffix-name" disabled
|
||||||
|
placeholder="Suffix"
|
||||||
|
:value="old('suffix')" required autofocus autocomplete="suffix"/>
|
||||||
|
<x-input-error :messages="$errors->get('suffix')" class="mt-2"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Value / Suffix -->
|
<!-- Schedule -->
|
||||||
<x-input-label for="value" value="Value and suffix" class="mt-4"
|
<div class="mt-6">
|
||||||
id="habit-suffix-label"/>
|
<x-input-label for="schedule-unit" value="Schedule"></x-input-label>
|
||||||
|
<x-text-input id="schedule-amount" class="inline-block mt-1" type="number"
|
||||||
|
placeholder="Numeric value" min="0"
|
||||||
|
name="schedule-amount"/>
|
||||||
|
|
||||||
<x-text-input id="habit-value-amount" class="inline-block mt-1 w-20" type="number"
|
<select name="schedule-unit" id="schedule-unit"
|
||||||
placeholder="" min="0" value="1"
|
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">
|
||||||
name="value" required disabled/>
|
<option value="day">Days</option>
|
||||||
<x-input-error :messages="$errors->get('value')" class="mt-2"/>
|
<option value="week">Weeks</option>
|
||||||
|
<option value="month">Months</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
<x-text-input id="habit-suffix-name" class="inline-block mt-1 disabled:opacity-50 w-1/2"
|
|
||||||
type="text" name="suffix" disabled required
|
|
||||||
placeholder="Suffix"
|
|
||||||
:value="old('suffix')" 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 Recurrence"></x-input-label>
|
|
||||||
<div class="inline-block mt-1 pr-1">
|
|
||||||
Every
|
|
||||||
</div>
|
|
||||||
<x-text-input id="schedule-value" class="inline-block mt-1 w-20" type="number"
|
|
||||||
placeholder="" min="0" value="1"
|
|
||||||
name="schedule_value"/>
|
|
||||||
<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">
|
|
||||||
<option value="day">days</option>
|
|
||||||
<option value="week">weeks</option>
|
|
||||||
<option value="month">months</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<div class="inline-block mt-1 px-1">
|
|
||||||
starting
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<x-text-input type="date" class="inline-block mt-1" name="schedule_start" id="schedule_start"
|
<!-- Goal -->
|
||||||
value="{{$today}}"
|
<div class="mt-6">
|
||||||
required></x-text-input>
|
<x-input-label value="Goal Type"></x-input-label>
|
||||||
|
<div class="text-sm my-3">
|
||||||
</div>
|
Adding a goal changes the display mode from the value and suffix to a calculated percentage.
|
||||||
</x-pagecard>
|
</div>
|
||||||
|
<div class="flex items-center mb-1">
|
||||||
<!-- Goal -->
|
<input id="goal-type-1" type="radio" value="none" name="goal-type"
|
||||||
<x-pagecard>
|
onclick="toggleGoalSchedule(true)"
|
||||||
<div class="">
|
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">
|
||||||
<x-input-label value="Goal Type"></x-input-label>
|
<label for="goal-type-1" class="ml-2">No goal</label>
|
||||||
<div class="text-sm my-3">
|
</div>
|
||||||
Adding a goal changes the display mode from the value and suffix to a calculated
|
<div class="flex items-center mb-1">
|
||||||
percentage.
|
<input id="goal-type-2" type="radio" value="schedule" name="goal-type"
|
||||||
</div>
|
checked="checked" onclick="toggleGoalSchedule(true)"
|
||||||
<div class="flex items-center mb-1">
|
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">
|
||||||
<input id="goal-type-1" type="radio" value="none" name="goal_type"
|
<label for="goal-type-2" class="ml-2 ">Same as schedule</label>
|
||||||
onclick="toggleGoalSchedule(true)"
|
</div>
|
||||||
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">
|
<div class="flex items-center mb-1">
|
||||||
<label for="goal-type-1" class="ml-2">No goal</label>
|
<input id="goal-type-3" type="radio" value="custom" name="goal-type"
|
||||||
</div>
|
onclick="toggleGoalSchedule(false)"
|
||||||
<div class="flex items-center mb-1">
|
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">
|
||||||
<input id="goal-type-2" type="radio" value="schedule" name="goal_type"
|
<label for="goal-type-3" class="ml-2 ">Custom schedule</label>
|
||||||
checked onclick="toggleGoalSchedule(true)"
|
</div>
|
||||||
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 Recurrence"></x-input-label>
|
|
||||||
<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="1" placeholder="" min="0" disabled required
|
|
||||||
name="goal_value"/>
|
|
||||||
<x-input-error :messages="$errors->get('goal_value')" class="mt-2"/>
|
|
||||||
|
|
||||||
<select name="goal_unit" id="goal-schedule-unit"
|
|
||||||
disabled required
|
|
||||||
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">
|
|
||||||
<option value="day">days</option>
|
|
||||||
<option value="week">weeks</option>
|
|
||||||
<option value="month">months</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<div class="inline-block mt-1 px-1">
|
|
||||||
starting
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<x-text-input type="date" class="inline-block mt-1" name="goal_start" id="goal_start"
|
<!-- goal-schedule -->
|
||||||
value="{{$today}}" disabled
|
<div class="mt-6">
|
||||||
required></x-text-input>
|
<x-input-label for="goal-schedule-unit" value="Goal Schedule"></x-input-label>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Priority -->
|
<x-text-input id="goal-schedule-amount" class="inline-block mt-1" type="number"
|
||||||
|
placeholder="Numeric value" min="0" disabled
|
||||||
|
name="goal-schedule-amount"/>
|
||||||
|
|
||||||
</x-pagecard>
|
<select name="goal-schedule-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>
|
||||||
|
|
||||||
</div>
|
<!-- Priority -->
|
||||||
|
|
||||||
<!-- Submit -->
|
</form>
|
||||||
<div class="w-full">
|
|
||||||
<div class=" my-6 float-right">
|
|
||||||
<x-primary-button class="px-20 py-2">Create habit</x-primary-button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function toggleHabitValueSuffix(value) {
|
function toggleHabitValueSuffix(value) {
|
||||||
document.getElementById('habit-value-amount').disabled = value;
|
document.getElementById('habit-value-amount').disabled = value;
|
||||||
@ -190,7 +132,6 @@ function toggleHabitValueSuffix(value) {
|
|||||||
function toggleGoalSchedule(value) {
|
function toggleGoalSchedule(value) {
|
||||||
document.getElementById('goal-schedule-amount').disabled = value;
|
document.getElementById('goal-schedule-amount').disabled = value;
|
||||||
document.getElementById('goal-schedule-unit').disabled = value;
|
document.getElementById('goal-schedule-unit').disabled = value;
|
||||||
document.getElementById('goal_start').disabled = value;
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -17,23 +17,19 @@
|
|||||||
<br>
|
<br>
|
||||||
|
|
||||||
{{-- Table--}}
|
{{-- Table--}}
|
||||||
|
|
||||||
<table class="table-auto text-left text-gray-500 dark:text-gray-400">
|
<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" class="px-4 py-2">
|
<th scope="col" class="px-4 py-2">
|
||||||
Category
|
Habits
|
||||||
</th>
|
|
||||||
<th scope="col" class="px-4 py-2">
|
|
||||||
Habit
|
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" class="px-6 py-2">
|
<th scope="col" class="px-6 py-2">
|
||||||
Tags
|
{{-- Edit--}}
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" class="px-6 py-2">
|
<th scope="col" class="px-6 py-2">
|
||||||
|
{{-- Delete--}}
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" class="px-6 py-2">
|
<th>
|
||||||
|
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
@ -41,34 +37,26 @@
|
|||||||
<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)}}" method="get">
|
<form action="{{route('habits.show', $habit)}}" method="get">
|
||||||
@csrf
|
@csrf
|
||||||
<x-secondary-button type="submit">View</x-secondary-button>
|
<x-secondary-button>View</x-secondary-button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-4 py-2">
|
<td class="px-4 py-2">
|
||||||
<form action="{{route('entries.create')}}" method="post">
|
<form action="{{route('habits.edit', $habit)}}" method="get">
|
||||||
@csrf
|
@csrf
|
||||||
<input type="hidden" name="habit" value="{{$habit->id}}">
|
<x-primary-button>Edit</x-primary-button>
|
||||||
<x-primary-button>Insert</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>
|
||||||
@ -76,7 +64,44 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{{-- <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>--}}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
<x-app-layout>
|
|
||||||
<x-slot name="header">
|
|
||||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
|
||||||
{{ __('Habit Details') }}
|
|
||||||
</h2>
|
|
||||||
</x-slot>
|
|
||||||
|
|
||||||
<div class="py-6">
|
|
||||||
<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="p-6 text-gray-900 dark:text-gray-100">
|
|
||||||
{{ $habit->name }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="py-6">
|
|
||||||
<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="p-6 text-gray-900 dark:text-gray-100">
|
|
||||||
<table class="table-auto text-left text-gray-700 dark:text-gray-400">
|
|
||||||
<thead class="text-gray-900 bg-gray-100 dark:bg-gray-700 dark:text-gray-200">
|
|
||||||
<tr>
|
|
||||||
<th scope="col" class="px-4 py-2">
|
|
||||||
Date
|
|
||||||
</th>
|
|
||||||
<th scope="col" class="px-6 py-2">
|
|
||||||
Note
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@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">
|
|
||||||
<td class="text-left px-4 py-2">
|
|
||||||
{{$entry->date}}
|
|
||||||
</td>
|
|
||||||
<td class="px-4 py-2">
|
|
||||||
{{$entry->note}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</x-app-layout>
|
|
@ -21,7 +21,7 @@
|
|||||||
<!-- 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>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hidden space-x-8 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')" :active="request()->routeIs('habits.*')">
|
<x-nav-link :href="route('habits.index')" :active="request()->routeIs('habits.index')">
|
||||||
{{ __('Habits') }}
|
{{ __('Habits') }}
|
||||||
</x-nav-link>
|
</x-nav-link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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,7 +30,4 @@
|
|||||||
|
|
||||||
Route::resource('/habits', HabitController::class);
|
Route::resource('/habits', HabitController::class);
|
||||||
|
|
||||||
Route::resource('/habits/entries', EntryController::class);
|
|
||||||
Route::post('/habits/entries/create', [EntryController::class, 'createWithHabit'] );
|
|
||||||
|
|
||||||
require __DIR__.'/auth.php';
|
require __DIR__.'/auth.php';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user