feat: add basic specimen functionality

This commit is contained in:
Alyx D Batte 2025-11-24 09:51:00 -05:00
parent 5280d46d07
commit 1c26a7801c
8 changed files with 214 additions and 2 deletions

View File

@ -0,0 +1,105 @@
<?php
namespace App\Livewire\Forms;
use App\Models\Specimen;
use Livewire\Attributes\Validate;
use Livewire\Form;
class SpecimenForm extends Form
{
#[Validate('required')]
public string $date = '';
#[Validate('required')]
public string $family = '';
#[Validate('required')]
public string $genus = '';
#[Validate('required')]
public string $specificEpithet = '';
#[Validate('required')]
public string $collector = '';
#[Validate('required')]
public string $collectionNumber = '';
public array $associateCollectors = [];
#[Validate('required')]
public string $plantHabit = '';
#[Validate('required')]
public string $populationSize = '';
#[Validate('required')]
public string $substrate = '';
#[Validate('required')]
public string $phenologyFlowering = '';
#[Validate('required')]
public string $phenologyFruiting = '';
#[Validate('required')]
public string $phenologyFruitingFlowering = '';
#[Validate('required')]
public string $phenologyVegetative = '';
public string $phenologyNotes = '';
#[Validate('required')]
public string $vegetationCommunity = '';
public array $plantAssociates = [];
#[Validate('required')]
public string $aspect = '';
#[Validate('required')]
public string $exposure = '';
#[Validate('required')]
public string $elevation = '';
#[Validate('required')]
public string $location = '';
public string $latitude = '';
public string $longitude = '';
public function store()
{
$this->validate();
Specimen::create($this->only([
'date',
'family',
'genus',
'specificEpithet',
'collector',
'collectionNumber',
'associateCollectors',
'plantHabit',
'populationSize',
'substrate',
'phenologyFlowering',
'phenologyFruiting',
'phenologyFruitingFlowering',
'phenologyVegetative',
'phenologyNotes',
'vegetationCommunity',
'plantAssociates',
'aspect',
'exposure',
'elevation',
'location',
'latitude',
'longitude',
]));
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Livewire\Herbarium;
use App\Livewire\Forms\SpecimenForm;
use Livewire\Component;
class CreateSpecimen extends Component
{
public SpecimenForm $form;
public function render()
{
return view('livewire.herbarium.create-specimen');
}
public function save()
{
$this->form->store();
return $this->redirect('/herbarium/list');
}
}

View File

@ -5,6 +5,7 @@
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Specimen extends Model
{
@ -13,6 +14,43 @@ class Specimen extends Model
protected $table = 'specimens';
protected $fillable = [
''
]
'date',
'family',
'genus',
'specific_epithet',
'collector',
'collection_number',
'associate_collectors',
'plant_habit', // herb, vine, shrub, liana, shrub, subshrub, tree
'population_size',
'substrate',
'phenology_flowering',
'phenology_fruiting',
'phenology_fruiting_flowering',
'phenology_notes',
'phenology_vegetative',
'vegetation_community',
'plant_associates',
'aspect',
'exposure',
'elevation',
'location',
'latitude',
'longitude',
'user_id',
];
public function user(): HasOne
{
return $this->hasOne(User::class,'id','user_id');
}
protected function casts(): array
{
return [
'date' => 'date',
'associate_collectors' => 'array',
'plant_associates' => 'array',
];
}
}

View File

@ -4,6 +4,7 @@
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
@ -37,6 +38,11 @@ class User extends Authenticatable
'remember_token',
];
public function specimens(): HasMany
{
return $this->hasMany(Specimen::class);
}
/**
* Get the attributes that should be cast.
*

View File

@ -0,0 +1,26 @@
<?php
namespace App\View\Components\Forms;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class textInput extends Component
{
/**
* Create a new component instance.
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.forms.text-input');
}
}

View File

@ -15,6 +15,10 @@
<flux:navlist.group :heading="__('Platform')" class="grid">
<flux:navlist.item icon="home" :href="route('dashboard')" :current="request()->routeIs('dashboard')" wire:navigate>{{ __('Dashboard') }}</flux:navlist.item>
</flux:navlist.group>
<flux:navlist.group :heading="__('Specimens')" class="grid">
<flux:navlist.item :href="route('specimen.create')" :current="request()->routeIs('specimen.create')" wire:navigate>{{ __('Add New') }}</flux:navlist.item>
</flux:navlist.group>
</flux:navlist>
<flux:spacer />

View File

@ -0,0 +1,5 @@
<div>
<h1>Specimens - {{ $header }}</h1>
<flux:separator class="my-8" />
{{ $slot }}
</div>

View File

@ -1,5 +1,6 @@
<?php
use App\Livewire\Herbarium\CreateSpecimen;
use App\Livewire\Settings\Appearance;
use App\Livewire\Settings\Password;
use App\Livewire\Settings\Profile;
@ -33,3 +34,7 @@
)
->name('two-factor.show');
});
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('specimens/create', CreateSpecimen::class)->name('specimen.create');
});