diff --git a/app/Enums/ShowRepeatType.php b/app/Enums/ShowRepeatType.php
index a1c30cd..1660e0e 100644
--- a/app/Enums/ShowRepeatType.php
+++ b/app/Enums/ShowRepeatType.php
@@ -15,7 +15,14 @@ enum ShowRepeatType: int
return constant("self::$name");
}
- public static function fromValue(int $value){
- return constant("self::$value");
+
+ public static function fromValue(string $value){
+ foreach (self::cases() as $case) {
+ if ($case->value === $value) {
+ return $case;
+ }
+ }
+
+ throw new \InvalidArgumentException("No matching UserType found for value: $value");
}
}
diff --git a/app/Filters/Show/ShowDaysFilters.php b/app/Filters/Show/ShowDaysFilters.php
new file mode 100644
index 0000000..1e56121
--- /dev/null
+++ b/app/Filters/Show/ShowDaysFilters.php
@@ -0,0 +1,37 @@
+ IsFilter::class,
+ ];
+
+ public function apply($query, $filters)
+ {
+ foreach ($this->receivedFilters($filters) as $name => $value) {
+ switch ($name) {
+ case 'all':
+ $name = array_diff(array_keys($this->filters), ['all']);
+ $filterInstance = new $this->filters['all']();
+ break;
+ default:
+ $filterInstance = new $this->filters[$name]();
+ break;
+ }
+ $query = $filterInstance($query, $name, $value);
+ }
+
+ return $query;
+ }
+
+
+ public function receivedFilters($filters)
+ {
+ return $filters->only(array_keys($this->filters));
+ }
+}
\ No newline at end of file
diff --git a/app/Helpers/CarbonShowRepetition.php b/app/Helpers/CarbonShowRepetition.php
index 989afe3..beee78c 100644
--- a/app/Helpers/CarbonShowRepetition.php
+++ b/app/Helpers/CarbonShowRepetition.php
@@ -40,6 +40,7 @@ class CarbonShowRepetition
while ($currentDate->lte($dateStopInterval)) {
if ($repeatTypeEnum === ShowRepeatType::monthly) {
$nextMonth = $currentDate->addMonth();
+ // With a flag we can skip this check and repeating based on the given month number
if ($nextMonth->day > $currentDate->day) {
$nextMonth->day = $currentDate->day;
}
@@ -52,4 +53,13 @@ class CarbonShowRepetition
return $dates;
}
+
+ public static function getNextStartDate(string $showFirstDate, int $showDayNumber): Carbon {
+ $date = Carbon::createFromFormat('Y-m-d', $showFirstDate);
+ $dayOfWeek = $date->dayOfWeek;
+ if($dayOfWeek != $showDayNumber){
+ $date = $date->next($showDayNumber);
+ }
+ return $date;
+ }
}
\ No newline at end of file
diff --git a/app/Http/Controllers/Show/ShowController.php b/app/Http/Controllers/Show/ShowController.php
index e4d217c..fe03d6a 100644
--- a/app/Http/Controllers/Show/ShowController.php
+++ b/app/Http/Controllers/Show/ShowController.php
@@ -42,16 +42,17 @@ class ShowController extends Controller
public function store(Request $request)
{
try {
- $showInfos = $request->show;
- $showDaysRules = $request->showDaysRules;
- $showDjs = $request->showDjs;
- $show = Show::firstOrCreate($showInfos);
- $this->manageShowDays($show, $showDaysRules);
- $this->manageShowDjs($showDjs, $show);
- }catch(Exception $e){
+ $showData = $request->all();
+ $showDays = $showData['show_days'];
+ $showDJs = $showData['show_djs'];
+ $this->createShow($showData, $showDays, $showDJs);
+ return response()->json([
+ 'status' => 'success',
+ 'message' => 'Show saved successfully!'
+ ]);
+ } catch (Exception $e) {
return response()->json(['message' => $e->getMessage()], 500);
}
- return response()->json(['message' => 'Show created successfully']);
}
public function show(ShowResource $show)
diff --git a/app/Http/Controllers/Show/ShowDaysController.php b/app/Http/Controllers/Show/ShowDaysController.php
new file mode 100644
index 0000000..0c8e96f
--- /dev/null
+++ b/app/Http/Controllers/Show/ShowDaysController.php
@@ -0,0 +1,49 @@
+except('flattenShowDays'));
+ $showDays = (new ShowDays())->searchFilter($queryParams)->get();
+ if($request->flattenShowDays) $showDays = $this->showDaysFlat($showDays);
+ return response()->json($showDays);
+ }
+
+ public function store(ShowDaysRequest $request)
+ {
+ return new ShowDaysResource(ShowDays::create($request->validated()));
+ }
+
+ public function show(ShowDays $ShowDays)
+ {
+ return new ShowDaysResource($ShowDays);
+ }
+
+ public function update(ShowDaysRequest $request, ShowDays $ShowDays)
+ {
+ $ShowDays->update($request->validated());
+
+ return new ShowDaysResource($ShowDays);
+ }
+
+ public function destroy(ShowDays $ShowDays)
+ {
+ $ShowDays->delete();
+
+ return response()->json();
+ }
+}
diff --git a/app/Models/Show/ShowDays.php b/app/Models/Show/ShowDays.php
index 6aca293..ff74aa0 100644
--- a/app/Models/Show/ShowDays.php
+++ b/app/Models/Show/ShowDays.php
@@ -2,6 +2,7 @@
namespace App\Models\Show;
+use App\Filters\Show\ShowDaysFilters;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -41,4 +42,9 @@ class ShowDays extends Model
{
return $this->belongsTo(Show::class, 'show_id');
}
+
+ public function scopeSearchFilter($query, $request) {
+ $filters = new ShowDaysFilters();
+ return $filters->apply($query, $request);
+ }
}
diff --git a/app/Traits/Show/ShowDaysTrait.php b/app/Traits/Show/ShowDaysTrait.php
index 7b301b4..a6df44b 100644
--- a/app/Traits/Show/ShowDaysTrait.php
+++ b/app/Traits/Show/ShowDaysTrait.php
@@ -3,9 +3,12 @@
namespace App\Traits\Show;
use App\Enums\ShowRepeatType;
+use App\Helpers\CarbonShowRepetition;
+use App\Helpers\Preferences;
use App\Lib\RabbitMQSender;
+use Illuminate\Support\Collection;
-Trait ShowDaysTrait
+trait ShowDaysTrait
{
/**
* Each show may have a repetition rules, we set them in the db
@@ -13,42 +16,43 @@ Trait ShowDaysTrait
* @param $showDaysRules
*
* @return void
+ * @throws \Exception
*/
- public function createShowDays($show, $showDays)
+ public function createShowDays($show, $showDays): void
{
- for ($i = 0; $i < count($showDays['day']); $i++) {
- $showDay = $showDays;
- $showDay['repeat_type'] = ShowRepeatType::fromName($showDays['repeat_type']);
- $showDay['day'] = $showDays['day'][$i];
-
- // Check if showDay already exists for this day and show ID
- $existingShowDay = $show->showDays()->where('day', $showDay['day'])->first();
-
- if ($existingShowDay) {
- $existingShowDay->update([
- 'first_show' => $showDay['first_show'],
- 'start_time' => $showDay['start_time'],
- 'timezone' => $showDay['timezone'],
- 'duration' => $showDay['duration'],
- 'repeat_type' => $showDay['repeat_type']->value,
- ]);
- continue;
+ try {
+ // TODO this is incorrect, look up the preference helper, getDefaultTimezone is called statically but it should not
+ $timezone = config('app.timezone');
+ foreach ($showDays['day'] as $day) {
+ $showDay = $showDays;
+ $showDay['first_show'] = CarbonShowRepetition::getNextStartDate($showDays['first_show'], $day);
+ $showDay['repeat_type'] = ShowRepeatType::fromName($showDays['repeat_type'])->value;
+ $showDay['day'] = $day;
+ $show->showDays()->create(
+ [
+ 'first_show' => $showDay['first_show'],
+ 'start_time' => $showDay['start_time'],
+ 'timezone' => $showDay['timezone'],
+ 'duration' => $showDay['duration'],
+ 'repeat_type' => $showDay['repeat_type'],
+ 'day' => $showDay['day'],
+ 'timezone' => $timezone,
+ ]
+ );
}
- $show->showDays()->create($showDay);
+ } catch (\Exception $e) {
+ throw new \Exception($e->getMessage());
}
}
- public function manageShowDays($show, $showDays)
- {
- // TODO Determine if the show days rules have been changed
- // By editing the createShowDays, returning the days on which the rules have been changed
- // one could trigger the creation of only specific instances
- // The hard part relies on finding out which show instances
- // belong to which showDays rules, as they do not have any fk to showDays
- // Probably its complexity is higher than its advantages
- // if it is, then proceed to edit the show days rules and generate the show instances
- $this->createShowDays($show, $showDays);
- $this->manageShowInstances($show);
- RabbitMQSender::SendMessageToPypo('update_schedule', []);
+ public function showDaysFlat(Collection $showDays): array {
+ $baseProps = $showDays->first()->toArray();
+ $earliestDate = $showDays->min('first_show');
+ $daysArray = $showDays->pluck('day')->toArray();
+
+ return array_merge($baseProps, [
+ 'first_show' => $earliestDate,
+ 'day' => $daysArray,
+ ]);
}
}
\ No newline at end of file
diff --git a/app/Traits/Show/ShowDjTrait.php b/app/Traits/Show/ShowDjTrait.php
index fa7281f..e9da290 100644
--- a/app/Traits/Show/ShowDjTrait.php
+++ b/app/Traits/Show/ShowDjTrait.php
@@ -11,7 +11,7 @@ trait ShowDjTrait
/**
* @throws Exception
*/
- public function manageShowDjs(array $showDjs, Show $show)
+ public function manageShowDjs(Show $show, array $showDjs)
{
// TODO Add protection so only Editor and Admin can edit the djs
@@ -22,21 +22,26 @@ trait ShowDjTrait
}
}
- // Fetch current DJs for the show
- $currentDjs = $show->showDjs()->pluck('subjs_id')->toArray();
+ try {
+ // Fetch current DJs for the show
+ $currentDjs = $show->showDjs()->pluck('subjs_id')->toArray();
- // Compute the difference
- $djsToAdd = array_diff($showDjs, $currentDjs);
- $djsToRemove = array_diff($currentDjs, $showDjs);
+ // Compute the difference
+ $djsToAdd = array_diff($showDjs, $currentDjs);
+ $djsToRemove = array_diff($currentDjs, $showDjs);
- // Remove DJs not in the list
- foreach ($djsToRemove as $djId) {
- $show->showDjs()->where('subjs_id', $djId)->delete();
+ // Remove DJs not in the list
+ foreach ($djsToRemove as $djId) {
+ $show->showDjs()->where('subjs_id', $djId)->delete();
+ }
+
+ // Add new DJs
+ foreach ($djsToAdd as $djId) {
+ $show->showDjs()->make(['subjs_id' => $djId]);
+ }
+ } catch (\Exception $e) {
+ return $e->getMessage();
}
- // Add new DJs
- foreach ($djsToAdd as $djId) {
- $show->showDjs()->updateOrCreate(['subjs_id' => $djId]);
- }
}
}
\ No newline at end of file
diff --git a/app/Traits/Show/ShowInstancesTrait.php b/app/Traits/Show/ShowInstancesTrait.php
index c17a802..c6c0cde 100644
--- a/app/Traits/Show/ShowInstancesTrait.php
+++ b/app/Traits/Show/ShowInstancesTrait.php
@@ -6,6 +6,7 @@ use App\Helpers\CarbonShowRepetition;
use App\Helpers\LengthFormatter;
use App\Http\Resources\ShowResource;
use App\Models\Preference;
+use App\Models\Show\Show;
use App\Models\ShowInstances\ShowInstances;
use Carbon\Carbon;
use Carbon\CarbonInterval;
@@ -18,33 +19,31 @@ trait ShowInstancesTrait
*/
public function checkOverlappingInstances(array $instancesDates, $duration, int $showId): void
{
+ $existingRanges = ShowInstances::where('show_id', '!=', $showId)
+ ->get(['starts', 'ends'])
+ ->map(fn($i) => [$i->starts, $i->ends]);
+
foreach ($instancesDates as $date) {
- $instanceStartDate = $date;
- $instanceEndDate = clone $date;
- $instanceEndDate->addHours($duration);
+ $newStart = $date;
+ $newEnd = (clone $date)->addHours($duration);
- // Query to check for overlaps
- $overlapExists = ShowInstances::where(
- function ($query) use ($instanceStartDate, $instanceEndDate, $showId) {
- $query->where('starts', '<=', $instanceEndDate)
- ->where('ends', '>=', $instanceStartDate)
- ->where('show_id','!=', $showId);
- }
- )->exists();
+ $hasOverlap = $existingRanges->contains(
+ fn($range) => $newStart < $range[1] && $newEnd > $range[0]
+ );
- if ($overlapExists) {
- throw new Exception('Overlapping shows'); // Overlap found
+ if ($hasOverlap) {
+ throw new Exception("Overlap detected between $newStart and $newEnd");
}
}
}
- public function createShowInstances($instancesDates, $showDay, $show)
+ public function createShowInstances($instancesDates, $showDayDuration, $showId)
{
$showInstances = [];
foreach ($instancesDates as $instanceDate) {
$showStartDate = $instanceDate->copy();
- $duration = CarbonInterval::createFromFormat('H:i:s', $showDay->duration);
+ $duration = CarbonInterval::createFromFormat('H:i', $showDayDuration);
$showEndDate = $showStartDate->copy()->add($duration);
$timeFilled = LengthFormatter::generateStringTimeFilled($showStartDate, $showEndDate);
@@ -53,7 +52,7 @@ trait ShowInstancesTrait
$showInstances[] = [
'starts' => $showStartDate,
'ends' => $showEndDate,
- 'show_id' => $show->id,
+ 'show_id' => $showId,
'record' => 0,
'rebroadcast' => 0,
'time_filled' => $timeFilled,
@@ -73,34 +72,36 @@ trait ShowInstancesTrait
* @param ShowResource $ShowResource
*
* @return void
- * @throws \Exception
+ * @throws Exception
*/
- public function manageShowInstances($show)
+ public function manageShowInstances(Show $show)
{
- $showDays = $show->showDays;
- $generationLimitDate = Preference::where('keystr', 'shows_populated_until')->value('valstr');
- $generationLimitDate = Carbon::createFromFormat('Y-m-d H:i:s', $generationLimitDate);
- $showInstances = [];
+ try {
+ $generationLimitDate = Preference::where('keystr', 'shows_populated_until')->value('valstr');
+ $generationLimitDate = Carbon::createFromFormat('Y-m-d H:i:s', $generationLimitDate);
+ $showInstances = [];
+ foreach ($show->showDays as $showDay) {
+ try {
+ $lastShowDate = $showDay->last_show ?? $generationLimitDate;
+ $instancesDates = CarbonShowRepetition::generateDates(
+ $showDay->repeat_type,
+ $showDay->first_show,
+ $showDay->start_time,
+ $lastShowDate
+ );
- foreach ($showDays as $showDay) {
- try {
- $lastShowDate = $showDay->last_show ?? $generationLimitDate;
- $instancesDates = CarbonShowRepetition::generateDates(
- $showDay->repeat_type,
- $showDay->first_show,
- $showDay->start_time,
- $lastShowDate
- );
+ $this->checkOverlappingInstances($instancesDates, $showDay->duration, $show->id);
- $this->checkOverlappingInstances($instancesDates, $showDay->duration, $show->id);
-
- $showInstances[] = $this->createShowInstances($instancesDates, $showDay, $show);
- } catch (\Exception $e) {
- throw new \Exception($e->getMessage(), 500);
+ $showInstances[] = $this->createShowInstances($instancesDates, $showDay->duration, $show->id);
+ } catch (Exception $e) {
+ throw new Exception($e->getMessage(), 500);
+ }
}
- }
- foreach ($showInstances as $showInstance) {
- $show->showInstances()->createMany($showInstance);
+ foreach ($showInstances as $showInstance) {
+ $show->showInstances()->createMany($showInstance);
+ }
+ } catch (Exception $e) {
+ throw new Exception($e->getMessage(), 500);
}
}
}
\ No newline at end of file
diff --git a/app/Traits/Show/ShowTrait.php b/app/Traits/Show/ShowTrait.php
index a2d191b..76136b3 100644
--- a/app/Traits/Show/ShowTrait.php
+++ b/app/Traits/Show/ShowTrait.php
@@ -2,7 +2,39 @@
namespace App\Traits\Show;
+use App\Lib\RabbitMQSender;
+use App\Models\Show\Show;
+use App\Models\Show\ShowHosts;
+use Illuminate\Support\Facades\DB;
+
trait ShowTrait
{
-
+ /**
+ * @param array $showData
+ * @param ShowDays[] $showDays
+ * @param ShowHosts[] $showDJs
+ *
+ * @return string|void
+ * @throws \Exception
+ */
+ public function createShow(array $showData, array $showDays, array|null $showDJs)
+ {
+ try {
+ DB::beginTransaction();
+ $show = Show::create($showData);
+ $this->createShowDays($show, $showDays);
+ if (isset($showDJs)) {
+ $this->manageShowDjs($show, $showDJs);
+ }
+ $this->manageShowInstances($show);
+ $show->save();
+ DB::commit();
+ RabbitMQSender::SendMessageToPypo('update_schedule', []);
+ } catch (\Exception $e) {
+ DB::rollBack();
+ throw new \Exception($e->getMessage());
+ } catch (\Throwable $e) {
+ throw new \Exception($e->getMessage());
+ }
+ }
}
diff --git a/resources/js/components/content/Dashboard.vue b/resources/js/components/content/Dashboard.vue
index fb1b805..b21384f 100644
--- a/resources/js/components/content/Dashboard.vue
+++ b/resources/js/components/content/Dashboard.vue
@@ -1,20 +1,21 @@
-
-
import {WeekDaysData} from "@models/show/ShowRepetition.ts";
+import type {PropType} from "vue";
+import type {Show} from "@models/show/show.ts";
const selectedDays = defineModel()
+
+const props = defineProps({
+ fixedDay: {
+ type: Number,
+ required: false,
+ },
+});
@@ -14,6 +22,7 @@ const selectedDays = defineModel()
v-model="selectedDays"
:label="day.dayName"
:value="day.type"
+ :disabled="day.type === props.fixedDay"
/>
diff --git a/resources/js/components/content/partials/fields/show/ShowStartEndTime.vue b/resources/js/components/content/partials/fields/show/ShowStartEndTime.vue
index 6659c42..806c86a 100644
--- a/resources/js/components/content/partials/fields/show/ShowStartEndTime.vue
+++ b/resources/js/components/content/partials/fields/show/ShowStartEndTime.vue
@@ -2,7 +2,8 @@
import {onMounted, type PropType} from "vue";
import { ref, watch } from 'vue';
import {getShowInstances} from "@models/show/showInstance.ts";
-
+import {getHoursMinutesFromString, getTimeDiff} from "@/helpers/DateFormatter.ts";
+// Emits, props and models
const emits = defineEmits(['update:duration'])
const props = defineProps({
@@ -25,37 +26,26 @@ const props = defineProps({
})
const startTime = defineModel({default: '08:00'});
+
+// Data
const duration = ref('0:0');
const endTime = ref('');
const startMenu = ref(false);
const endMenu = ref(false);
-const getDuration = (startTime: Date, endTime: Date) => {
- const diffInMilliseconds = Math.abs(startTime.getTime() - endTime.getTime());
- const remainingHours = Math.floor((diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
- const remainingMinutes = Math.floor((diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60));
-
- return `${remainingHours}:${remainingMinutes}`;
-};
-
-const getHoursMinutes = (timeString: string) => {
- const [ h, m ] = timeString.split(":");
- const ms = new Date().setHours(h,m);
- return new Date(ms)
-};
-
+// Func
const checkTime = () => {
if (startTime.value && endTime) {
- const start = getHoursMinutes(startTime.value);
- let end = getHoursMinutes(endTime.value);
+ const start: Date = getHoursMinutesFromString(startTime.value);
+ let end: Date = getHoursMinutesFromString(endTime.value);
if (end.getTime() <= start.getTime()) {
end = new Date(start);
end.setMinutes(start.getMinutes() + 60);
endTime.value = end.toLocaleTimeString('en-US', { hour12: false, hour: '2-digit', minute: '2-digit' });;
}
- duration.value = getDuration(start, end);
+ duration.value = getTimeDiff(start, end);
emits('update:duration', duration.value);
}
}
diff --git a/resources/js/components/content/partials/CalendarShowEvent.vue b/resources/js/components/content/partials/show/CalendarShowEvent.vue
similarity index 98%
rename from resources/js/components/content/partials/CalendarShowEvent.vue
rename to resources/js/components/content/partials/show/CalendarShowEvent.vue
index 575e969..d72f9a1 100644
--- a/resources/js/components/content/partials/CalendarShowEvent.vue
+++ b/resources/js/components/content/partials/show/CalendarShowEvent.vue
@@ -3,7 +3,7 @@ import type { PropType} from "vue";
import type {ContextMenuType} from "@models/misc/contextMenu"
import type {calendarShowEvent, ShowEventActionTrigger} from "@models/misc/calendarShowEvent.ts";
import {calendarShowEventMenu} from "@models/misc/calendarShowEvent";
-import {ref, computed, onMounted} from 'vue';
+import { ref } from 'vue';
import ContextMenu from '@partials/ContextMenu.vue';
const emit = defineEmits([
diff --git a/resources/js/components/content/partials/show/ShowCreateEditForm.vue b/resources/js/components/content/partials/show/ShowForm.vue
similarity index 61%
rename from resources/js/components/content/partials/show/ShowCreateEditForm.vue
rename to resources/js/components/content/partials/show/ShowForm.vue
index 8bce39e..cd70a2c 100644
--- a/resources/js/components/content/partials/show/ShowCreateEditForm.vue
+++ b/resources/js/components/content/partials/show/ShowForm.vue
@@ -7,6 +7,7 @@ import {getUser} from "@models/User.ts";
import {getPlaylist} from "@models/playlist.ts";
import ColorPickerButton from "@partials/fields/misc/ColorPickerButton.vue";
+// Props
const props = defineProps({
show: {
type: Object as PropType,
@@ -14,18 +15,22 @@ const props = defineProps({
},
});
+// Data
let usersDJs = ref([])
let playlists = ref([])
-const isLoading = ref(false);
+const loading = ref(false);
const showScheduleFormMode = ref(false);
+const isFormValid = ref(false);
+// Store
+const showStore = useShowStore()
+showStore.loadShow(props.show)
-const showFormStore = useShowStore()
+// Funcs
onMounted(async () => {
- isLoading.value = true
- await showFormStore.loadShow(props.show)
+ loading.value = true
usersDJs.value = await getUser({role: 'dj'});
playlists.value = await getPlaylist({});
- isLoading.value = false
+ loading.value = false
})
const toggleScheduleForm = () => {
@@ -34,32 +39,45 @@ const toggleScheduleForm = () => {
-
+
+
+
+
+
Trasmissione
-
+
showFormStore.updateField({ key: 'name', value })"
+ @update:modelValue="value => showStore.updateField({ key: 'name', value })"
+ :rules="[v => !!v || 'Nome รจ obbligatorio']"
+ required="true"
/>
@@ -68,11 +86,11 @@ const toggleScheduleForm = () => {
showFormStore.updateField({ key: 'url', value })"
+ @update:modelValue="value => showStore.updateField({ key: 'url', value })"
/>
@@ -81,11 +99,11 @@ const toggleScheduleForm = () => {
showFormStore.updateField({ key: 'genre', value })"
+ @update:modelValue="value => showStore.updateField({ key: 'genre', value })"
/>
@@ -94,11 +112,11 @@ const toggleScheduleForm = () => {
showFormStore.updateField({ key: 'description', value })"
+ @update:modelValue="value => showStore.updateField({ key: 'description', value })"
/>
@@ -107,9 +125,9 @@ const toggleScheduleForm = () => {
showFormStore.updateField({ key: 'backgroundColor', value })"
+ @update:modelValue="value => showStore.updateField({ key: 'backgroundColor', value })"
/>
@@ -118,11 +136,11 @@ const toggleScheduleForm = () => {
showFormStore.updateField({ key: 'imagePath', value })"
+ @update:modelValue="value => showStore.updateField({ key: 'imagePath', value })"
/>
@@ -133,24 +151,24 @@ const toggleScheduleForm = () => {
showFormStore.updateField({ key: 'autoplaylistRepeat', value })"
+ :disabled="!showStore.currentShow.hasAutoplaylist"
+ @update:modelValue="value => showStore.updateField({ key: 'autoplaylistRepeat', value })"
/>
showFormStore.updateField({ key: 'autoplaylistId', value })"
+ :disabled="!showStore.currentShow.hasAutoplaylist"
+ @update:modelValue="value => showStore.updateField({ key: 'autoplaylistId', value })"
/>
@@ -160,14 +178,14 @@ const toggleScheduleForm = () => {
showFormStore.updateField({ key: 'showDjs', value })"
+ @update:modelValue="value => showStore.updateField({ key: 'showDjs', value })"
/>
@@ -176,8 +194,8 @@ const toggleScheduleForm = () => {
Torna indietro
- Salva
- Salva e schedula
+ Salva
+ Regole di programmazione
diff --git a/resources/js/components/content/partials/show/ShowScheduleForm.vue b/resources/js/components/content/partials/show/ShowScheduleForm.vue
index 56784bd..2a9fd06 100644
--- a/resources/js/components/content/partials/show/ShowScheduleForm.vue
+++ b/resources/js/components/content/partials/show/ShowScheduleForm.vue
@@ -1,39 +1,65 @@
-
@@ -41,18 +67,19 @@ watch(checkBoxRepetition, (checkBoxRepetition) => {
Regole di programmazione
-
+
showFormStore.updateShowDaysField({ key: 'firstShow', value })"
+ required="true"
+ v-on:update:modelValue="updateShowStartDay"
/>
@@ -63,8 +90,8 @@ watch(checkBoxRepetition, (checkBoxRepetition) => {
v-model="checkBoxEnd"
>
{
showFormStore.updateShowDaysField({ key: 'duration', value })"
+ @update:duration="value => showStore.updateShowDaysField({ key: 'duration', value })"
+ required="true"
/>
@@ -90,7 +118,7 @@ watch(checkBoxRepetition, (checkBoxRepetition) => {
v-model="checkBoxRepetition"
>
{
/>
showStore.updateShowDaysField({ key: 'day', value })"
label="Giorni"
- :disabled="!checkBoxRepetition"
- @update:modelValue="value => showFormStore.updateShowDaysField({ key: 'day', value })"
/>
@@ -111,7 +140,7 @@ watch(checkBoxRepetition, (checkBoxRepetition) => {
Torna indietro
- Salva
+ Salva
diff --git a/resources/js/composables/content/models/show/ShowRepetition.ts b/resources/js/composables/content/models/show/ShowRepetition.ts
index 9d8b4bf..99e26ed 100644
--- a/resources/js/composables/content/models/show/ShowRepetition.ts
+++ b/resources/js/composables/content/models/show/ShowRepetition.ts
@@ -1,33 +1,31 @@
-enum ShowRepeatEnum {
- Weekly = 0,
- Biweekly = 1,
- Triweekly = 4,
- FourWeeks = 5,
- Monthly = 2,
+// TODO i18n strings
+export enum ShowRepeatEnum {
+ weekly = 'Weekly',
+ biweekly = 'Biweekly',
+ triweekly = 'Triweekly',
+ fourWeeks = 'Four weeks',
+ monthly = 'Monthly',
+ noRepeat = 'No repeat',
}
export interface ShowRepetitionType {
type: ShowRepeatEnum;
- repeatName: string
}
-export const showRepetitionData: ShowRepetitionType[] = [
- { type: ShowRepeatEnum.Weekly, repeatName: "Weekly" },
- { type: ShowRepeatEnum.Biweekly, repeatName: "Biweekly" },
- { type: ShowRepeatEnum.Triweekly, repeatName: "Triweekly" },
- { type: ShowRepeatEnum.FourWeeks, repeatName: "Four Weeks" },
- { type: ShowRepeatEnum.Monthly, repeatName: "Monthly" },
-];
+export const showRepetitionData: ShowRepetitionType[] = Object.entries(ShowRepeatEnum).map(([key, value]) => ({
+ type: key as ShowRepeatEnum,
+ repeatName: value,
+}));
enum WeekDaysEnum {
- Monday = 0,
- Tuesday = 1,
- Wednesday = 2,
- Thursday = 3,
- Friday = 4,
- Saturday = 5,
- Sunday = 6,
+ Monday = 1,
+ Tuesday = 2,
+ Wednesday = 3,
+ Thursday = 4,
+ Friday = 5,
+ Saturday = 6,
+ Sunday = 0,
}
export interface WeekDays {
diff --git a/resources/js/composables/content/models/show/show.ts b/resources/js/composables/content/models/show/show.ts
index 8abbb6e..4a98aae 100644
--- a/resources/js/composables/content/models/show/show.ts
+++ b/resources/js/composables/content/models/show/show.ts
@@ -1,6 +1,6 @@
import type {ShowInstance} from "@models/show/showInstance.ts";
import type {ShowDays} from "@models/show/showDays";
-import type {ShowDjs} from "@models/show/showDjs";
+import type {ShowDJs} from "@models/show/showDJs.ts";
import axios, {type AxiosResponse} from "axios";
import {cleanOptions} from "@/helpers/AxiosHelper.ts";
@@ -18,13 +18,13 @@ export interface Show {
liveStreamPass?: string;
imagePath?: string | File;
hasAutoplaylist: boolean;
- autoplaylist_id?: number;
+ autoplaylistId?: number;
autoplaylistRepeat: boolean;
// Relationships
block?: any;
showDays?: ShowDays;
- showDjs?: ShowDjs[];
+ showDjs?: ShowDJs[];
showInstances?: ShowInstance[];
playlist?: any;
}
@@ -32,7 +32,7 @@ export interface Show {
export const baseShow = (): Show => {
return {
id: null,
- name: '',
+ name: 'Esempio',
url: '',
genre: '',
description: '',
@@ -42,7 +42,7 @@ export const baseShow = (): Show => {
liveStreamPass: '',
imagePath: '',
hasAutoplaylist: false,
- autoplaylist_id: 0,
+ autoplaylistId: null,
autoplaylistRepeat: false,
showDjs: null,
showDays: null,
diff --git a/resources/js/composables/content/models/show/showDjs.ts b/resources/js/composables/content/models/show/showDJs.ts
similarity index 86%
rename from resources/js/composables/content/models/show/showDjs.ts
rename to resources/js/composables/content/models/show/showDJs.ts
index 4490169..cf2a8b4 100644
--- a/resources/js/composables/content/models/show/showDjs.ts
+++ b/resources/js/composables/content/models/show/showDJs.ts
@@ -1,6 +1,6 @@
import { VTextField } from "vuetify/components";
-export interface ShowDjs {
+export interface ShowDJs {
id?: number;
subjsId: number;
showId: number;
@@ -11,7 +11,7 @@ export interface User {
login: string;
}
-export function showDjsForm(item: ShowDjs) {
+export function showDjsForm(item: ShowDJs) {
const visibleFields = {
subjsId: 'Presentatore',
showId: 'Programma'
@@ -22,7 +22,7 @@ export function showDjsForm(item: ShowDjs) {
Object.keys(visibleFields).forEach((key) => {
fields[key] = {
label: visibleFields[key],
- value: item[key as keyof ShowDjs],
+ value: item[key as keyof ShowDJs],
component: VTextField,
disabled: false
};
diff --git a/resources/js/composables/content/models/show/showDays.ts b/resources/js/composables/content/models/show/showDays.ts
index fd06a7f..1d1e139 100644
--- a/resources/js/composables/content/models/show/showDays.ts
+++ b/resources/js/composables/content/models/show/showDays.ts
@@ -1,6 +1,8 @@
import axios, {type AxiosResponse} from "axios";
-import {cleanOptions} from "@/helpers/AxiosHelper.ts";
+import {cleanOptions, snakeToCamel} from "@/helpers/AxiosHelper.ts";
+import type {ShowRepetitionType} from "@models/show/ShowRepetition.ts";
+//TODO RepeatType should use the interface ShowRepetitionType
export interface ShowDays {
id?: number;
firstShow: Date;
@@ -9,7 +11,7 @@ export interface ShowDays {
timezone: string;
duration: string;
day: number[];
- repeatType: number;
+ repeatType: string;
nextPopDate?: string;
showId?: number;
record?: number;
@@ -22,8 +24,8 @@ export const baseShowDays = ():ShowDays => {
startTime: '08:00',
timezone: '',
duration: '01:00',
- day: [0],
- repeatType: 0,
+ day: [],
+ repeatType: 'noRepeat',
nextPopDate: '',
showId: 0,
record: 0
@@ -31,14 +33,14 @@ export const baseShowDays = ():ShowDays => {
}
export const getShowDays = async (options: {
- showId?: number | null;
+ show_id?: number | null;
flattenShowDays?: boolean;
}): Promise => {
const filteredParams = cleanOptions(options);
return await axios.get(`/showDays`, {params: filteredParams})
.then((response: AxiosResponse) => {
- return response.data
+ return snakeToCamel(response.data);
}).catch((error: Error) => {
console.log("Error: " + error);
})
diff --git a/resources/js/helpers/AxiosHelper.ts b/resources/js/helpers/AxiosHelper.ts
index da3c385..d3d1d7d 100644
--- a/resources/js/helpers/AxiosHelper.ts
+++ b/resources/js/helpers/AxiosHelper.ts
@@ -2,4 +2,30 @@ export function cleanOptions(options: Object): Object {
return Object.fromEntries(
Object.entries(options).filter(([_, value]) => value !== undefined && value !== null)
);
-}
\ No newline at end of file
+}
+
+export function camelToSnake(obj) {
+ if (Array.isArray(obj)) {
+ return obj.map(camelToSnake);
+ } else if (obj !== null && typeof obj === 'object') {
+ return Object.keys(obj).reduce((acc, key) => {
+ const snakeKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
+ acc[snakeKey] = camelToSnake(obj[key]);
+ return acc;
+ }, {});
+ }
+ return obj;
+}
+
+export function snakeToCamel(obj) {
+ if (Array.isArray(obj)) {
+ return obj.map(snakeToCamel);
+ } else if (obj !== null && typeof obj === 'object') {
+ return Object.keys(obj).reduce((acc, key) => {
+ const camelKey = key.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
+ acc[camelKey] = snakeToCamel(obj[key]);
+ return acc;
+ }, {});
+ }
+ return obj;
+}
diff --git a/resources/js/helpers/DateFormatter.ts b/resources/js/helpers/DateFormatter.ts
index e88a961..d6e2e51 100644
--- a/resources/js/helpers/DateFormatter.ts
+++ b/resources/js/helpers/DateFormatter.ts
@@ -9,5 +9,23 @@ export function extractTime(dateTimeString: string, extractTime: boolean = false
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${hours}:${minutes}`;
}
- return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
-};
\ No newline at end of file
+ return date.getFullYear() + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0');
+};
+
+export function getTimeDiff(startTime: Date, endTime: Date) {
+ const diffInMilliseconds = Math.abs(startTime.getTime() - endTime.getTime());
+
+ const hours = Math.floor((diffInMilliseconds % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
+ const minutes = Math.floor((diffInMilliseconds % (1000 * 60 * 60)) / (1000 * 60));
+
+ const formattedHours = String(hours).padStart(2, '0');
+ const formattedMinutes = String(minutes).padStart(2, '0');
+
+ return `${formattedHours}:${formattedMinutes}`;
+}
+
+export function getHoursMinutesFromString(timeString: string): Date {
+ const [ h, m ] = timeString.split(":");
+ const ms = new Date().setHours(h,m);
+ return new Date(ms)
+}
\ No newline at end of file
diff --git a/resources/js/stores/show.store.ts b/resources/js/stores/show.store.ts
index d098281..a06cb69 100644
--- a/resources/js/stores/show.store.ts
+++ b/resources/js/stores/show.store.ts
@@ -1,6 +1,9 @@
-import { defineStore } from 'pinia'
-import { type Show } from '@models/show/show'
+import {defineStore} from 'pinia'
+import {type Show} from '@models/show/show'
import type {ShowDays} from "@models/show/showDays";
+import axios, {type AxiosResponse} from "axios";
+import {camelToSnake} from "@/helpers/AxiosHelper.ts";
+import {extractTime} from "@/helpers/DateFormatter.ts";
export const useShowStore = defineStore('show', {
state: () => ({
@@ -9,23 +12,46 @@ export const useShowStore = defineStore('show', {
}),
actions: {
async loadShow(showData: Show) {
- this.currentShow = { ...showData }
+ this.currentShow = {...showData}
},
updateField(payload: { key: string; value: any }) {
this.currentShow[payload.key] = payload.value
},
- async saveShow() {
- // Implement API call to save this.currentShow
- },
- async saveSchedule() {
- // Implement schedule saving logic
- },
- resetShowDays() {
- this.currentShow.showDays = { ...this.baseShowDays };
- },
-
updateShowDaysField(payload: { key: string; value: any }) {
this.currentShow.showDays[payload.key] = payload.value;
- }
+ },
+ async createShow() {
+ let showData = {...this.currentShow};
+ showData.showDays.firstShow = extractTime(showData.showDays.firstShow);
+ if (showData.showDays.lastShow) {
+ showData.showDays.lastShow = extractTime(showData.showDays.lastShow);
+ }
+ showData = camelToSnake(showData);
+ return await axios.post(`/show`, showData)
+ .then((response: AxiosResponse) => {
+ return response.data
+ }).catch((error: Error) => {
+ console.log("Error: " + error);
+ })
+ },
+ async updateShow() {
+ return await axios.post(`/show`, this.currentShow)
+ .then((response: AxiosResponse) => {
+ return response.data
+ }).catch((error: Error) => {
+ console.log("Error: " + error.message);
+ })
+ },
+ async updateShowDays() {
+ return await axios.post(`/showDays`, this.currentShow.showDays)
+ .then((response: AxiosResponse) => {
+ return response.data
+ }).catch((error: Error) => {
+ console.log("Error: " + error);
+ })
+ },
+ resetShowDays() {
+ this.currentShow.showDays = {...this.baseShowDays};
+ },
}
})
\ No newline at end of file
diff --git a/resources/js/stores/showInstance.store.ts b/resources/js/stores/showInstance.store.ts
index c9ad79b..3f27a5d 100644
--- a/resources/js/stores/showInstance.store.ts
+++ b/resources/js/stores/showInstance.store.ts
@@ -18,7 +18,10 @@ export const useShowInstanceStore = defineStore('showInstance', {
this.currentShowInstance = baseShowInstance()
},
async saveShowInstance() {
- // Implement API call to save this.currentShowInstance
+
+ },
+ async updateShowInstance() {
+
},
}
})
\ No newline at end of file
diff --git a/routes/web.php b/routes/web.php
index ddcff75..ef043d5 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -3,6 +3,7 @@
use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\FileController;
use App\Http\Controllers\Show\ShowController;
+use App\Http\Controllers\Show\ShowDaysController;
use App\Http\Controllers\ShowInstance\ShowInstancesController;
use App\Http\Controllers\SmartBlockController;
use App\Http\Controllers\TrackTypeController;
@@ -33,6 +34,7 @@ Route::resources([
'playlist' => PlaylistController::class,
'smartblock' => SmartBlockController::class,
'show' => ShowController::class,
+ 'showDays' => ShowDaysController::class,
'showInstances' => ShowInstancesController::class,
'user' => UserController::class,
], [