|
@@ -22,7 +22,13 @@ class AppointmentController extends Controller
|
|
|
{
|
|
|
public function events(Request $request)
|
|
|
{
|
|
|
- $proIds = explode(',', $request->get('proIds'));
|
|
|
+ if(empty($request->get('proIds'))) {
|
|
|
+ $proIds = [];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $proIds = explode(',', $request->get('proIds'));
|
|
|
+ }
|
|
|
+
|
|
|
$start = $request->get('start');
|
|
|
$end = $request->get('end');
|
|
|
$clientId = $request->get('clientId');
|
|
@@ -31,13 +37,19 @@ class AppointmentController extends Controller
|
|
|
// get appointments
|
|
|
$appointments = Appointment
|
|
|
::where('start_time', '>=', $start)
|
|
|
- ->where('start_time', '<=', $end)
|
|
|
- ->where(function ($query) use ($proIds, $clientId) {
|
|
|
- $query
|
|
|
- ->whereIn('pro_id', $proIds)
|
|
|
- ->orWhere('client_id', '=', $clientId);
|
|
|
- })
|
|
|
- ->get();
|
|
|
+ ->where('start_time', '<=', $end);
|
|
|
+
|
|
|
+ if(count($proIds)) {
|
|
|
+ $appointments = $appointments
|
|
|
+ ->where(function ($query) use ($proIds, $clientId) {
|
|
|
+ $query
|
|
|
+ ->whereIn('pro_id', $proIds)
|
|
|
+ ->orWhere('client_id', '=', $clientId);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ $appointments = $appointments->get();
|
|
|
+
|
|
|
$events = [];
|
|
|
foreach ($appointments as $appointment) {
|
|
|
$events[] = [
|
|
@@ -60,166 +72,170 @@ class AppointmentController extends Controller
|
|
|
];
|
|
|
}
|
|
|
|
|
|
- // get availability
|
|
|
- $genAvail = ProGeneralAvailability
|
|
|
- ::where('is_cancelled', false)
|
|
|
- ->whereIn('pro_id', $proIds)
|
|
|
- ->get();
|
|
|
- $specAvail = ProSpecificAvailability
|
|
|
- ::where('is_cancelled', false)
|
|
|
- ->whereIn('pro_id', $proIds)
|
|
|
- ->where(function ($query) use ($start, $end) {
|
|
|
- $query
|
|
|
- ->where(function ($query2) use ($start, $end) {
|
|
|
- $query2
|
|
|
- ->where('start_time', '>=', $start)
|
|
|
- ->where('start_time', '<=', $end);
|
|
|
- })
|
|
|
- ->orWhere(function ($query2) use ($start, $end) {
|
|
|
- $query2
|
|
|
- ->where('end_time', '>=', $start)
|
|
|
- ->where('end_time', '<=', $end);
|
|
|
- });
|
|
|
- })
|
|
|
- ->get();
|
|
|
- $specUnavail = ProSpecificUnavailability
|
|
|
- ::where('is_cancelled', false)
|
|
|
- ->whereIn('pro_id', $proIds)
|
|
|
- ->where(function ($query) use ($start, $end) {
|
|
|
- $query
|
|
|
- ->where(function ($query2) use ($start, $end) {
|
|
|
- $query2
|
|
|
- ->where('start_time', '>=', $start)
|
|
|
- ->where('start_time', '<=', $end);
|
|
|
- })
|
|
|
- ->orWhere(function ($query2) use ($start, $end) {
|
|
|
- $query2
|
|
|
- ->where('end_time', '>=', $start)
|
|
|
- ->where('end_time', '<=', $end);
|
|
|
- });
|
|
|
- })
|
|
|
- ->get();
|
|
|
-
|
|
|
- // logic
|
|
|
- // 1. enumerate days between start and end (inclusive)
|
|
|
+ if(count($proIds)) {
|
|
|
+
|
|
|
+ // get availability
|
|
|
+ $genAvail = ProGeneralAvailability
|
|
|
+ ::where('is_cancelled', false)
|
|
|
+ ->whereIn('pro_id', $proIds)
|
|
|
+ ->get();
|
|
|
+ $specAvail = ProSpecificAvailability
|
|
|
+ ::where('is_cancelled', false)
|
|
|
+ ->whereIn('pro_id', $proIds)
|
|
|
+ ->where(function ($query) use ($start, $end) {
|
|
|
+ $query
|
|
|
+ ->where(function ($query2) use ($start, $end) {
|
|
|
+ $query2
|
|
|
+ ->where('start_time', '>=', $start)
|
|
|
+ ->where('start_time', '<=', $end);
|
|
|
+ })
|
|
|
+ ->orWhere(function ($query2) use ($start, $end) {
|
|
|
+ $query2
|
|
|
+ ->where('end_time', '>=', $start)
|
|
|
+ ->where('end_time', '<=', $end);
|
|
|
+ });
|
|
|
+ })
|
|
|
+ ->get();
|
|
|
+ $specUnavail = ProSpecificUnavailability
|
|
|
+ ::where('is_cancelled', false)
|
|
|
+ ->whereIn('pro_id', $proIds)
|
|
|
+ ->where(function ($query) use ($start, $end) {
|
|
|
+ $query
|
|
|
+ ->where(function ($query2) use ($start, $end) {
|
|
|
+ $query2
|
|
|
+ ->where('start_time', '>=', $start)
|
|
|
+ ->where('start_time', '<=', $end);
|
|
|
+ })
|
|
|
+ ->orWhere(function ($query2) use ($start, $end) {
|
|
|
+ $query2
|
|
|
+ ->where('end_time', '>=', $start)
|
|
|
+ ->where('end_time', '<=', $end);
|
|
|
+ });
|
|
|
+ })
|
|
|
+ ->get();
|
|
|
+
|
|
|
+ // logic
|
|
|
+ // 1. enumerate days between start and end (inclusive)
|
|
|
// 2. for each pro
|
|
|
- // 3. calculate pairs of start-end of availability
|
|
|
-
|
|
|
- // 1. enumerate days between start and end (inclusive)
|
|
|
- $phpTZ = $this->appTZtoPHPTZ($timeZone);
|
|
|
- $startDate = new \DateTime($start, new \DateTimeZone($phpTZ));
|
|
|
- $endDate = new \DateTime($end, new \DateTimeZone($phpTZ));
|
|
|
- $endDate->setTime(23,59,59);
|
|
|
- $period = new \DatePeriod($startDate, \DateInterval::createFromDateString('1 day'), $endDate);
|
|
|
- $days = [];
|
|
|
- foreach ($period as $day) {
|
|
|
- $days[] = [
|
|
|
- "day" => strtoupper($day->format("l")), // SUNDAY, etc.
|
|
|
- "date" => $day->format("Y-m-d"), // 2020-10-04, etc.
|
|
|
- ];
|
|
|
- }
|
|
|
+ // 3. calculate pairs of start-end of availability
|
|
|
+
|
|
|
+ // 1. enumerate days between start and end (inclusive)
|
|
|
+ $phpTZ = $this->appTZtoPHPTZ($timeZone);
|
|
|
+ $startDate = new \DateTime($start, new \DateTimeZone($phpTZ));
|
|
|
+ $endDate = new \DateTime($end, new \DateTimeZone($phpTZ));
|
|
|
+ $endDate->setTime(23, 59, 59);
|
|
|
+ $period = new \DatePeriod($startDate, \DateInterval::createFromDateString('1 day'), $endDate);
|
|
|
+ $days = [];
|
|
|
+ foreach ($period as $day) {
|
|
|
+ $days[] = [
|
|
|
+ "day" => strtoupper($day->format("l")), // SUNDAY, etc.
|
|
|
+ "date" => $day->format("Y-m-d"), // 2020-10-04, etc.
|
|
|
+ ];
|
|
|
+ }
|
|
|
|
|
|
- foreach ($proIds as $proId) {
|
|
|
+ foreach ($proIds as $proId) {
|
|
|
|
|
|
- $proTimeLine = new TimeLine($startDate, $endDate);
|
|
|
+ $proTimeLine = new TimeLine($startDate, $endDate);
|
|
|
|
|
|
- $pro = Pro::where('id', $proId)->first();
|
|
|
+ $pro = Pro::where('id', $proId)->first();
|
|
|
|
|
|
- $proGenAvail = $genAvail->filter(function ($record) use ($proId) {
|
|
|
- return $record->pro_id == $proId;
|
|
|
- });
|
|
|
+ $proGenAvail = $genAvail->filter(function ($record) use ($proId) {
|
|
|
+ return $record->pro_id == $proId;
|
|
|
+ });
|
|
|
|
|
|
- // if no gen avail, assume mon to fri, 9 to 7
|
|
|
- if(!count($proGenAvail)) {
|
|
|
- $dayNames = ['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY'];
|
|
|
- foreach ($dayNames as $dayName) {
|
|
|
- $item = new \stdClass();
|
|
|
- $item->day_of_week = $dayName;
|
|
|
- $item->timezone = $timeZone;
|
|
|
- $item->start_time = '09:00:00';
|
|
|
- $item->end_time = '18:00:00';
|
|
|
- $proGenAvail->push($item);
|
|
|
+ // if no gen avail, assume mon to fri, 9 to 7
|
|
|
+ if (!count($proGenAvail)) {
|
|
|
+ $dayNames = ['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY'];
|
|
|
+ foreach ($dayNames as $dayName) {
|
|
|
+ $item = new \stdClass();
|
|
|
+ $item->day_of_week = $dayName;
|
|
|
+ $item->timezone = $timeZone;
|
|
|
+ $item->start_time = '09:00:00';
|
|
|
+ $item->end_time = '18:00:00';
|
|
|
+ $proGenAvail->push($item);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- $proSpecAvail = $specAvail->filter(function ($record) use ($proId) {
|
|
|
- return $record->pro_id == $proId;
|
|
|
- });
|
|
|
+ $proSpecAvail = $specAvail->filter(function ($record) use ($proId) {
|
|
|
+ return $record->pro_id == $proId;
|
|
|
+ });
|
|
|
|
|
|
- $proSpecUnavail = $specUnavail->filter(function ($record) use ($proId) {
|
|
|
- return $record->pro_id == $proId;
|
|
|
- });
|
|
|
+ $proSpecUnavail = $specUnavail->filter(function ($record) use ($proId) {
|
|
|
+ return $record->pro_id == $proId;
|
|
|
+ });
|
|
|
|
|
|
- // general availability
|
|
|
- foreach ($days as $day) {
|
|
|
+ // general availability
|
|
|
+ foreach ($days as $day) {
|
|
|
|
|
|
- $proGenAvailForTheDay = $proGenAvail->filter(function ($record) use ($day) {
|
|
|
- return $record->day_of_week === $day["day"];
|
|
|
- });
|
|
|
- foreach ($proGenAvailForTheDay as $ga) {
|
|
|
+ $proGenAvailForTheDay = $proGenAvail->filter(function ($record) use ($day) {
|
|
|
+ return $record->day_of_week === $day["day"];
|
|
|
+ });
|
|
|
+ foreach ($proGenAvailForTheDay as $ga) {
|
|
|
|
|
|
- $gaStart = new \DateTime($day["date"], new \DateTimeZone($this->appTZtoPHPTZ($ga->timezone)));
|
|
|
- $parts = explode(":", $ga->start_time);
|
|
|
- $gaStart->setTime(intval($parts[0]), intval($parts[1]), intval($parts[2]));
|
|
|
- $gaStart->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
+ $gaStart = new \DateTime($day["date"], new \DateTimeZone($this->appTZtoPHPTZ($ga->timezone)));
|
|
|
+ $parts = explode(":", $ga->start_time);
|
|
|
+ $gaStart->setTime(intval($parts[0]), intval($parts[1]), intval($parts[2]));
|
|
|
+ $gaStart->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
|
|
|
- $gaEnd = new \DateTime($day["date"], new \DateTimeZone($this->appTZtoPHPTZ($ga->timezone)));
|
|
|
- $parts = explode(":", $ga->end_time);
|
|
|
- $gaEnd->setTime(intval($parts[0]), intval($parts[1]), intval($parts[2]));
|
|
|
- $gaEnd->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
+ $gaEnd = new \DateTime($day["date"], new \DateTimeZone($this->appTZtoPHPTZ($ga->timezone)));
|
|
|
+ $parts = explode(":", $ga->end_time);
|
|
|
+ $gaEnd->setTime(intval($parts[0]), intval($parts[1]), intval($parts[2]));
|
|
|
+ $gaEnd->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
|
|
|
- $proTimeLine->addAvailability($gaStart, $gaEnd);
|
|
|
- }
|
|
|
+ $proTimeLine->addAvailability($gaStart, $gaEnd);
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- // specific availability
|
|
|
- foreach ($proSpecAvail as $sa) {
|
|
|
- $saStart = new \DateTime($sa->start_time, new \DateTimeZone($this->appTZtoPHPTZ($sa->timezone)));
|
|
|
- $saStart->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
- $saEnd = new \DateTime($sa->end_time, new \DateTimeZone($this->appTZtoPHPTZ($sa->timezone)));
|
|
|
- $saEnd->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
- $proTimeLine->addAvailability($saStart, $saEnd);
|
|
|
- }
|
|
|
+ // specific availability
|
|
|
+ foreach ($proSpecAvail as $sa) {
|
|
|
+ $saStart = new \DateTime($sa->start_time, new \DateTimeZone($this->appTZtoPHPTZ($sa->timezone)));
|
|
|
+ $saStart->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
+ $saEnd = new \DateTime($sa->end_time, new \DateTimeZone($this->appTZtoPHPTZ($sa->timezone)));
|
|
|
+ $saEnd->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
+ $proTimeLine->addAvailability($saStart, $saEnd);
|
|
|
+ }
|
|
|
|
|
|
- // specific unavailability
|
|
|
- foreach ($proSpecUnavail as $sua) {
|
|
|
- $suaStart = new \DateTime($sua->start_time, new \DateTimeZone($this->appTZtoPHPTZ($sua->timezone)));
|
|
|
- $suaStart->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
- $suaEnd = new \DateTime($sua->end_time, new \DateTimeZone($this->appTZtoPHPTZ($sua->timezone)));
|
|
|
- $suaEnd->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
- $proTimeLine->removeAvailability($suaStart, $suaEnd);
|
|
|
- }
|
|
|
+ // specific unavailability
|
|
|
+ foreach ($proSpecUnavail as $sua) {
|
|
|
+ $suaStart = new \DateTime($sua->start_time, new \DateTimeZone($this->appTZtoPHPTZ($sua->timezone)));
|
|
|
+ $suaStart->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
+ $suaEnd = new \DateTime($sua->end_time, new \DateTimeZone($this->appTZtoPHPTZ($sua->timezone)));
|
|
|
+ $suaEnd->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
+ $proTimeLine->removeAvailability($suaStart, $suaEnd);
|
|
|
+ }
|
|
|
|
|
|
- // make already booked slots unavailable
|
|
|
- $proAppointments = $appointments->filter(function ($record) use ($proId) {
|
|
|
- return $record->pro_id == $proId && !in_array($record->status, ['CANCELLED', 'COMPLETED', 'ABANDONED']);
|
|
|
- });
|
|
|
- foreach ($proAppointments as $appointment) {
|
|
|
- if($appointment->start_time && $appointment->end_time) {
|
|
|
- $appStart = $this->convertToTimezone($appointment->start_time, $timeZone, 'UTC', true);
|
|
|
- $appEnd = $this->convertToTimezone($appointment->end_time, $timeZone, 'UTC', true);
|
|
|
- $proTimeLine->removeAvailability($appStart, $appEnd);
|
|
|
+ // make already booked slots unavailable
|
|
|
+ $proAppointments = $appointments->filter(function ($record) use ($proId) {
|
|
|
+ return $record->pro_id == $proId && !in_array($record->status, ['CANCELLED', 'COMPLETED', 'ABANDONED']);
|
|
|
+ });
|
|
|
+ foreach ($proAppointments as $appointment) {
|
|
|
+ if ($appointment->start_time && $appointment->end_time) {
|
|
|
+ $appStart = $this->convertToTimezone($appointment->start_time, $timeZone, 'UTC', true);
|
|
|
+ $appEnd = $this->convertToTimezone($appointment->end_time, $timeZone, 'UTC', true);
|
|
|
+ $proTimeLine->removeAvailability($appStart, $appEnd);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- foreach ($proTimeLine->available as $item) {
|
|
|
+ foreach ($proTimeLine->available as $item) {
|
|
|
|
|
|
- $eStart = new \DateTime('@' . $item->start);
|
|
|
- $eStart->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
+ $eStart = new \DateTime('@' . $item->start);
|
|
|
+ $eStart->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
|
|
|
- $eEnd = new \DateTime('@' . $item->end);
|
|
|
- $eEnd->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
+ $eEnd = new \DateTime('@' . $item->end);
|
|
|
+ $eEnd->setTimezone(new \DateTimeZone($phpTZ));
|
|
|
|
|
|
- $events[] = [
|
|
|
- "type" => "availability",
|
|
|
- "title" => $pro->displayName() . " (available)",
|
|
|
- "proId" => $pro->id,
|
|
|
- "proUid" => $pro->uid,
|
|
|
- "start" => $eStart->format('Y-m-d H:i:s'),
|
|
|
- "end" => $eEnd->format('Y-m-d H:i:s'),
|
|
|
- "editable" => false
|
|
|
- ];
|
|
|
+ $events[] = [
|
|
|
+ "type" => "availability",
|
|
|
+ "title" => $pro->displayName() . " (available)",
|
|
|
+ "proId" => $pro->id,
|
|
|
+ "proUid" => $pro->uid,
|
|
|
+ "start" => $eStart->format('Y-m-d H:i:s'),
|
|
|
+ "end" => $eEnd->format('Y-m-d H:i:s'),
|
|
|
+ "editable" => false
|
|
|
+ ];
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|