Merge remote-tracking branch 'origin/main' into main_watanabe
All checks were successful
Deploy preview (main_watanabe) / deploy (push) Successful in 14s
All checks were successful
Deploy preview (main_watanabe) / deploy (push) Successful in 14s
This commit is contained in:
commit
33b4b3f69d
@ -2,35 +2,164 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Traits\AuthenticatesUser;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ParkDetailController extends Controller
|
||||
{
|
||||
public function show($park_id)
|
||||
{
|
||||
$park = DB::table('park')->where('park_id', $park_id)->first();
|
||||
use AuthenticatesUser;
|
||||
|
||||
$zones = DB::table('zone')
|
||||
/**
|
||||
* 駐輪場詳細情報を取得(Ajax用)
|
||||
*
|
||||
* @param string $management_code
|
||||
* @param int $park_id
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function show($management_code, $park_id)
|
||||
{
|
||||
if ($redirect = $this->handleSessionExpired('駐輪場詳細', false)) {
|
||||
return $redirect;
|
||||
}
|
||||
|
||||
$userId = session('user_id');
|
||||
$management = session('management');
|
||||
if (!$management) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 運営元情報取得失敗 user_id=" . $userId);
|
||||
return response()->json(['error' => 'Management not found'], 404);
|
||||
}
|
||||
|
||||
// マルチテナント対応:運営元に紐づく駐輪場のみ取得
|
||||
$park = $this->getParkInfo($park_id, $management->management_id);
|
||||
if (!$park) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 駐輪場情報取得失敗 park_id=" . $park_id . ", management_id=" . $management->management_id . ", user_id=" . $userId);
|
||||
return response()->json(['error' => 'Park not found'], 404);
|
||||
}
|
||||
|
||||
// ゾーン情報取得
|
||||
$zones = $this->getZones($park_id);
|
||||
|
||||
// 予約情報取得
|
||||
$reserves = $this->getReserves($park_id);
|
||||
|
||||
// 車種別の基準台数集計
|
||||
$zoneStandardSum = $this->calculateZoneStandardSum($zones);
|
||||
|
||||
// 車種別の空き台数計算
|
||||
$vacancyData = $this->calculateVacancy($zones, $reserves);
|
||||
|
||||
// 駐輪場ごとの更新可能期間取得
|
||||
$parkGracePeriod = $this->getParkGracePeriod($park_id);
|
||||
|
||||
\Log::info("[INFO] " . now()->format('Y-m-d H:i:s') . " 駐輪場詳細取得成功 park_id=" . $park_id . ", management_id=" . $management->management_id . ", user_id=" . $userId);
|
||||
|
||||
try {
|
||||
$html = view('regular_contract.park_detail', compact(
|
||||
'park',
|
||||
'zones',
|
||||
'reserves',
|
||||
'zoneStandardSum',
|
||||
'vacancyData',
|
||||
'parkGracePeriod'
|
||||
))->render();
|
||||
|
||||
\Log::info("[INFO] " . now()->format('Y-m-d H:i:s') . " ビュー生成成功 park_id=" . $park_id . ", HTML長=" . strlen($html));
|
||||
|
||||
|
||||
return response()->json(['html' => $html]);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " ビュー生成失敗 park_id=" . $park_id . ", error=" . $e->getMessage());
|
||||
return response()->json(['error' => 'View rendering failed'], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 駐輪場情報取得(マルチテナントフィルタ適用)
|
||||
*
|
||||
* 運営元に紐づく駐輪場のみを取得することで、他の運営元のデータが
|
||||
* 誤って表示されることを防ぐ。
|
||||
*
|
||||
* @param int $parkId
|
||||
* @param int $managementId
|
||||
* @return object|null
|
||||
*/
|
||||
private function getParkInfo(int $parkId, int $managementId)
|
||||
{
|
||||
try {
|
||||
return DB::table('park')
|
||||
->where('park_id', $parkId)
|
||||
->where('management_id', $managementId)
|
||||
->first();
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 駐輪場情報取得エラー park_id=" . $parkId . ", error=" . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ゾーン情報取得
|
||||
*
|
||||
* @param int $parkId
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function getZones(int $parkId)
|
||||
{
|
||||
try {
|
||||
return DB::table('zone')
|
||||
->leftJoin('psection', 'zone.psection_id', '=', 'psection.psection_id')
|
||||
->leftJoin('ptype', 'zone.ptype_id', '=', 'ptype.ptype_id')
|
||||
->select('zone.*', 'psection.psection_subject', 'ptype.ptype_subject')
|
||||
->where('zone.park_id', $park_id)
|
||||
->select(
|
||||
'zone.*',
|
||||
'psection.psection_subject',
|
||||
'ptype.ptype_subject'
|
||||
)
|
||||
->where('zone.park_id', $parkId)
|
||||
->get();
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " zone情報取得失敗 park_id=" . $parkId . ", error=" . $e->getMessage());
|
||||
return collect();
|
||||
}
|
||||
}
|
||||
|
||||
$reserves = DB::table('reserve')
|
||||
/**
|
||||
* 予約情報取得
|
||||
*
|
||||
* @param int $parkId
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function getReserves(int $parkId)
|
||||
{
|
||||
try {
|
||||
return DB::table('reserve')
|
||||
->join('zone', function ($join) {
|
||||
$join->on('reserve.psection_id', '=', 'zone.psection_id')
|
||||
->on('reserve.ptype_id', '=', 'zone.ptype_id');
|
||||
})
|
||||
->join('ptype', 'zone.ptype_id', '=', 'ptype.ptype_id')
|
||||
->where('reserve.park_id', $park_id)
|
||||
->where('reserve.park_id', $parkId)
|
||||
->where('reserve.valid_flag', 1)
|
||||
->select('reserve.*', 'ptype.ptype_subject')
|
||||
->get();
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " reserve情報取得失敗 park_id=" . $parkId . ", error=" . $e->getMessage());
|
||||
return collect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 車種別の基準台数集計
|
||||
*
|
||||
* 駐輪場の車種別定員(zone_standard の合計)を算出する。
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $zones
|
||||
* @return array
|
||||
*/
|
||||
private function calculateZoneStandardSum($zones)
|
||||
{
|
||||
$zoneStandardSum = [];
|
||||
|
||||
foreach ($zones as $zone) {
|
||||
$key = $zone->psection_subject; // 「自転車」「原付」など
|
||||
if (!isset($zoneStandardSum[$key])) {
|
||||
@ -39,14 +168,29 @@ class ParkDetailController extends Controller
|
||||
$zoneStandardSum[$key] += $zone->zone_standard;
|
||||
}
|
||||
|
||||
// 空き台数集計用配列
|
||||
return $zoneStandardSum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 車種別の空き台数計算
|
||||
*
|
||||
* 予約を考慮した実際の空き台数を算出する。
|
||||
* 許容台数から現在台数を引き、さらに有効な予約件数分を減算することで、正確な空き状況を把握する。
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $zones
|
||||
* @param \Illuminate\Support\Collection $reserves
|
||||
* @return array
|
||||
*/
|
||||
private function calculateVacancy($zones, $reserves)
|
||||
{
|
||||
$vacancyData = [];
|
||||
|
||||
// zone_tolerance - zone_number を集計
|
||||
foreach ($zones as $zone) {
|
||||
$key = $zone->psection_id . '_' . $zone->ptype_subject;
|
||||
if (!isset($vacancyData[$key])) {
|
||||
$vacancyData[$key] = 0;
|
||||
}
|
||||
// zone_tolerance - zone_number を合計
|
||||
$vacancyData[$key] += ($zone->zone_tolerance - $zone->zone_number);
|
||||
}
|
||||
|
||||
@ -54,23 +198,36 @@ class ParkDetailController extends Controller
|
||||
foreach ($reserves as $reserve) {
|
||||
$key = $reserve->psection_id . '_' . $reserve->ptype_subject;
|
||||
if (isset($vacancyData[$key])) {
|
||||
$vacancyData[$key] -= 1; // 1件分減算
|
||||
$vacancyData[$key] -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新期間取得
|
||||
$city_grace_periods = DB::table('city')
|
||||
->select('city_id', 'update_grace_period_start_date', 'update_grace_period_start_time', 'update_grace_period_end_date', 'update_grace_period_end_time')
|
||||
->whereIn('city_id', function ($query) {
|
||||
$query->select('city_id')->from('park');
|
||||
})
|
||||
->get()
|
||||
->keyBy('city_id');
|
||||
return $vacancyData;
|
||||
}
|
||||
|
||||
// 必要なら他テーブルJOINや追加情報も取得
|
||||
return response()->json([
|
||||
'html' => view('regular_contract.park_detail', compact('park', 'zones', 'reserves', 'zoneStandardSum', 'vacancyData', 'city_grace_periods'))->render()
|
||||
]);
|
||||
/**
|
||||
* 駐輪場の更新可能期間取得
|
||||
*
|
||||
* @param int $parkId
|
||||
* @return object|null
|
||||
*/
|
||||
private function getParkGracePeriod(int $parkId)
|
||||
{
|
||||
try {
|
||||
return DB::table('park')
|
||||
->select(
|
||||
'park_id',
|
||||
'update_grace_period_start_date',
|
||||
'update_grace_period_start_time',
|
||||
'update_grace_period_end_date',
|
||||
'update_grace_period_end_time'
|
||||
)
|
||||
->where('park_id', $parkId)
|
||||
->first();
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 駐輪場更新可能期間取得失敗 park_id=" . $parkId . ", error=" . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function showWait($reserve_id)
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Traits\AuthenticatesUser;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
@ -16,50 +17,175 @@ use Carbon\Carbon;
|
||||
|
||||
class RegularContractCreateController extends Controller
|
||||
{
|
||||
// 新規作成画面表示
|
||||
use AuthenticatesUser;
|
||||
|
||||
/**
|
||||
* 駐輪場選択画面を表示
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\View\View|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function show(Request $request)
|
||||
{
|
||||
$user_id = session('user_id');
|
||||
if (!$user_id) {
|
||||
return redirect('/login');
|
||||
if ($redirect = $this->handleSessionExpired('駐輪場選択')) {
|
||||
return $redirect;
|
||||
}
|
||||
$user = DB::table('user')->where('user_id', $user_id)->first();
|
||||
|
||||
// 市町村名(park→city JOINで重複排除)
|
||||
$cities = DB::table('park')
|
||||
$userId = session('user_id');
|
||||
$user = DB::table('user')->where('user_id', $userId)->first();
|
||||
|
||||
// マルチテナント対応のため、運営元情報をセッションから取得
|
||||
$management = session('management');
|
||||
if (!$management) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 運営元情報が見つからない user_id=" . $userId);
|
||||
abort(404);
|
||||
}
|
||||
|
||||
// 検索条件・ページング取得
|
||||
$cityId = $request->input('city_id');
|
||||
$stationName = $request->input('station_neighbor_station');
|
||||
$parkId = $request->input('park_id');
|
||||
$page = (int)$request->input('page', 1);
|
||||
$perPage = 10;
|
||||
|
||||
// ルート名で画面種別判定(新規定期契約 or 駐輪場検索)
|
||||
$isRegularContract = $request->route()->getName() === 'regular_contract.create';
|
||||
$activeMenu = $isRegularContract ? 'SWC-8-1' : 'SWC-10-1';
|
||||
|
||||
// マスタデータ取得(運営元フィルタ適用)
|
||||
$cities = $this->getCitiesList($management->management_id);
|
||||
$stations = $this->getStationsList($management->management_id);
|
||||
$parks = $this->getParksList($management->management_id);
|
||||
|
||||
// 運営元が取り扱う車種一覧を取得
|
||||
$availableVehicles = $this->getAvailableVehicles($management->management_id);
|
||||
|
||||
// 駐輪場テーブルデータ取得(検索・ページング、運営元フィルタ適用)
|
||||
$parksTableData = $this->getParksTableData($management->management_id, $cityId, $stationName, $parkId, $page, $perPage);
|
||||
|
||||
// zone・reserve マスタ取得(運営元フィルタ適用)
|
||||
$zones = $this->getZonesByParkId($management->management_id);
|
||||
$reserve = $this->getReserveByParkId($management->management_id);
|
||||
|
||||
// 駐輪場ごとの更新可能期間取得(運営元フィルタ適用)
|
||||
$parkGracePeriods = $this->getParkGracePeriods($management->management_id);
|
||||
|
||||
// 駐輪場ごと・車種ごとの状態を事前計算
|
||||
$parksTableData['data'] = $this->calculateVehicleStatus(
|
||||
$parksTableData['data'],
|
||||
$zones,
|
||||
$reserve,
|
||||
$parkGracePeriods,
|
||||
$availableVehicles
|
||||
);
|
||||
|
||||
// アクセスログ記録
|
||||
$screenName = $isRegularContract ? '新規定期契約登録' : '駐輪場検索';
|
||||
\Log::info("[INFO] " . now()->format('Y-m-d H:i:s') . " {$screenName}画面アクセス user_id=" . $userId . ", management_id=" . $management->management_id . ", city_id=" . ($cityId ?? 'null') . ", park_id=" . ($parkId ?? 'null'));
|
||||
|
||||
return view('regular_contract.create', [
|
||||
'active_menu' => $activeMenu,
|
||||
'user_name' => $user->user_name ?? '',
|
||||
'cities' => $cities,
|
||||
'stations' => $stations,
|
||||
'parks' => $parks,
|
||||
'parks_table' => $parksTableData['data'],
|
||||
'parks_table_total' => $parksTableData['total'],
|
||||
'parks_table_page' => $page,
|
||||
'parks_table_perPage' => $perPage,
|
||||
'available_vehicles' => $availableVehicles,
|
||||
'reserve' => $reserve,
|
||||
'isRegularContract' => $isRegularContract,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 市町村一覧取得(運営元フィルタ適用)
|
||||
* マルチテナント対応のため、運営元に紐づく駐輪場の市町村のみ表示
|
||||
*
|
||||
* @param int $managementId
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function getCitiesList(int $managementId)
|
||||
{
|
||||
try {
|
||||
return DB::table('park')
|
||||
->join('city', 'park.city_id', '=', 'city.city_id')
|
||||
->where('park.management_id', $managementId)
|
||||
->select('city.city_id', 'city.city_name')
|
||||
->distinct()
|
||||
->get();
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 市町村一覧取得失敗 management_id=" . $managementId . ", error=" . $e->getMessage());
|
||||
return collect();
|
||||
}
|
||||
}
|
||||
|
||||
// city_idごとの更新可能期間情報を取得
|
||||
$city_grace_periods = DB::table('city')
|
||||
->select('city_id', 'update_grace_period_start_date', 'update_grace_period_start_time', 'update_grace_period_end_date', 'update_grace_period_end_time')
|
||||
->get()
|
||||
->keyBy('city_id');
|
||||
|
||||
// 駅名(stationテーブルのstation_neighbor_station全件)
|
||||
$stations = DB::table('station')
|
||||
->select('station_neighbor_station')
|
||||
/**
|
||||
* 駅名一覧取得(運営元フィルタ適用)
|
||||
*
|
||||
* マルチテナント対応のため、運営元に紐づく駐輪場の駅のみ表示する。
|
||||
*
|
||||
* @param int $managementId
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function getStationsList(int $managementId)
|
||||
{
|
||||
try {
|
||||
return DB::table('station')
|
||||
->join('park', 'station.park_id', '=', 'park.park_id')
|
||||
->where('park.management_id', $managementId)
|
||||
->select('station.station_neighbor_station')
|
||||
->distinct()
|
||||
->get();
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 駅名一覧取得失敗 management_id=" . $managementId . ", error=" . $e->getMessage());
|
||||
return collect();
|
||||
}
|
||||
}
|
||||
|
||||
// 駐輪場名(parkテーブルのpark_name全件)
|
||||
$parks = DB::table('park')
|
||||
/**
|
||||
* 駐輪場名一覧取得(運営元フィルタ適用)
|
||||
*
|
||||
* マルチテナント対応のため、運営元に紐づく駐輪場のみ表示する。
|
||||
*
|
||||
* @param int $managementId
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function getParksList(int $managementId)
|
||||
{
|
||||
try {
|
||||
return DB::table('park')
|
||||
->where('management_id', $managementId)
|
||||
->select('park_id', 'park_name')
|
||||
->distinct()
|
||||
->get();
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 駐輪場名一覧取得失敗 management_id=" . $managementId . ", error=" . $e->getMessage());
|
||||
return collect();
|
||||
}
|
||||
}
|
||||
|
||||
// テーブル表示用データ(park/city/station JOIN, park_id昇順, 10件ずつページング)
|
||||
$page = request()->input('page', 1);
|
||||
$perPage = 10;
|
||||
$city_id = request()->input('city_id');
|
||||
$station_name = request()->input('station_neighbor_station');
|
||||
$park_id = request()->input('park_id');
|
||||
|
||||
/**
|
||||
* 駐輪場テーブルデータ取得(検索・ページング適用、運営元フィルタ適用)
|
||||
*
|
||||
* マルチテナント対応のため、運営元に紐づく駐輪場のみ表示する。
|
||||
*
|
||||
* @param int $managementId
|
||||
* @param int|null $cityId
|
||||
* @param string|null $stationName
|
||||
* @param int|null $parkId
|
||||
* @param int $page
|
||||
* @param int $perPage
|
||||
* @return array ['data' => Collection, 'total' => int]
|
||||
*/
|
||||
private function getParksTableData(int $managementId, $cityId, $stationName, $parkId, int $page, int $perPage)
|
||||
{
|
||||
try {
|
||||
$query = DB::table('park')
|
||||
->join('city', 'park.city_id', '=', 'city.city_id')
|
||||
->leftJoin('station', 'park.park_id', '=', 'station.park_id')
|
||||
->where('park.management_id', $managementId)
|
||||
->select(
|
||||
'park.park_id',
|
||||
'park.park_name',
|
||||
@ -70,94 +196,254 @@ class RegularContractCreateController extends Controller
|
||||
'station.station_name_ruby'
|
||||
);
|
||||
|
||||
if ($city_id) {
|
||||
$query->where('city.city_id', $city_id);
|
||||
// 検索条件適用
|
||||
if ($cityId) {
|
||||
$query->where('city.city_id', $cityId);
|
||||
}
|
||||
if ($station_name) {
|
||||
$query->where('station.station_neighbor_station', $station_name);
|
||||
if ($stationName) {
|
||||
$query->where('station.station_neighbor_station', $stationName);
|
||||
}
|
||||
if ($park_id) {
|
||||
$query->where('park.park_id', $park_id);
|
||||
if ($parkId) {
|
||||
$query->where('park.park_id', $parkId);
|
||||
}
|
||||
|
||||
// 並び替えパラメータ取得
|
||||
$sort = request()->input('sort', 'park_id');
|
||||
$order = request()->input('order', 'asc');
|
||||
$sortable = [
|
||||
'park_ruby' => 'park.park_ruby',
|
||||
'city_id' => 'city.city_id',
|
||||
'station_name_ruby' => 'station.station_name_ruby',
|
||||
'park_id' => 'park.park_id',
|
||||
];
|
||||
$query->orderBy('park.park_id', 'asc');
|
||||
|
||||
$total = $query->count();
|
||||
$parks_table = $query->get();
|
||||
|
||||
if ($sort === 'park_ruby' || $sort === 'station_name_ruby') {
|
||||
$collator = new \Collator('ja');
|
||||
$parks_table = $parks_table->sort(function ($a, $b) use ($order, $sort, $collator) {
|
||||
$a_val = $a->$sort ?? '';
|
||||
$b_val = $b->$sort ?? '';
|
||||
return $order === 'asc'
|
||||
? $collator->compare($a_val, $b_val)
|
||||
: $collator->compare($b_val, $a_val);
|
||||
})->values();
|
||||
} else {
|
||||
// park_id, city_idなどはSQLのorderByで十分なので、ここでPHPソートは不要
|
||||
if (isset($sortable[$sort])) {
|
||||
$parks_table = $parks_table->sortBy($sort, SORT_REGULAR, $order === 'desc')->values();
|
||||
// ページング適用
|
||||
$data = $query
|
||||
->skip(($page - 1) * $perPage)
|
||||
->take($perPage)
|
||||
->get();
|
||||
|
||||
\Log::info("[INFO] " . now()->format('Y-m-d H:i:s') . " 駐輪場データ取得成功 management_id=" . $managementId . ", 件数=" . $total . ", page=" . $page);
|
||||
|
||||
return [
|
||||
'data' => $data,
|
||||
'total' => $total,
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 駐輪場テーブルデータ取得失敗 management_id=" . $managementId . ", error=" . $e->getMessage());
|
||||
return [
|
||||
'data' => collect(),
|
||||
'total' => 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
$page = request()->input('page', 1);
|
||||
$perPage = 10;
|
||||
$parks_table = $parks_table->slice(($page - 1) * $perPage, $perPage)->values();
|
||||
|
||||
// zoneテーブルデータを取得(psectionテーブルとJOINしてpsection_subjectも取得)
|
||||
$zones = DB::table('zone')
|
||||
/**
|
||||
* ゾーンデータを park_id でグループ化して取得(運営元フィルタ適用)
|
||||
*
|
||||
* マルチテナント対応のため、運営元に紐づく駐輪場のゾーンのみ取得する。
|
||||
*
|
||||
* @param int $managementId
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function getZonesByParkId(int $managementId)
|
||||
{
|
||||
try {
|
||||
return DB::table('zone')
|
||||
->join('park', 'zone.park_id', '=', 'park.park_id')
|
||||
->leftJoin('psection', 'zone.psection_id', '=', 'psection.psection_id')
|
||||
->select('zone.zone_id', 'zone.park_id', 'zone.ptype_id', 'zone.psection_id', 'zone.zone_number', 'zone.zone_tolerance', 'psection.psection_subject')
|
||||
->where('park.management_id', $managementId)
|
||||
->select(
|
||||
'zone.zone_id',
|
||||
'zone.park_id',
|
||||
'zone.ptype_id',
|
||||
'zone.psection_id',
|
||||
'zone.zone_number',
|
||||
'zone.zone_tolerance',
|
||||
'psection.psection_subject'
|
||||
)
|
||||
->get()
|
||||
->groupBy('park_id');
|
||||
|
||||
// 空き予約マスタデータを取得
|
||||
$reserve = DB::table('reserve')
|
||||
->select('reserve_id', 'park_id', 'ptype_id', 'psection_id')
|
||||
->where('valid_flag', 1)
|
||||
->get()
|
||||
->groupBy('park_id');
|
||||
|
||||
// ルート名で画面表示を切り替え(新規定期契約 or 駐輪場検索)
|
||||
$isRegularContract = $request->route()->getName() === 'regular_contract.create';
|
||||
|
||||
// ヘッダーの選択状態を分岐
|
||||
$active_menu = $isRegularContract ? 'SWC-8-1' : 'SWC-10-1';
|
||||
|
||||
if ($isRegularContract) {
|
||||
\Log::info('新規定期契約-駐輪場選択画面にアクセス', [
|
||||
'user_id' => $user_id,
|
||||
]);
|
||||
} else {
|
||||
\Log::info('駐輪場検索-駐輪場選択画面にアクセス', [
|
||||
'user_id' => $user_id,
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " zone データ取得失敗 management_id=" . $managementId . ", error=" . $e->getMessage());
|
||||
return collect();
|
||||
}
|
||||
}
|
||||
|
||||
return view('regular_contract.create', [
|
||||
'active_menu' => $active_menu, // この画面のID
|
||||
'user_name' => $user ? $user->user_name : '', // ユーザー名(ヘッダー用)
|
||||
'cities' => $cities,
|
||||
'stations' => $stations,
|
||||
'parks' => $parks,
|
||||
'parks_table' => $parks_table,
|
||||
'parks_table_total' => $total,
|
||||
'parks_table_page' => $page,
|
||||
'parks_table_perPage' => $perPage,
|
||||
'zones' => $zones,
|
||||
'city_grace_periods' => $city_grace_periods,
|
||||
'reserve' => $reserve,
|
||||
'isRegularContract' => $isRegularContract
|
||||
]);
|
||||
/**
|
||||
* 予約データを park_id でグループ化して取得(運営元フィルタ適用)
|
||||
*
|
||||
* マルチテナント対応のため、運営元に紐づく駐輪場の予約のみ取得する。
|
||||
*
|
||||
* @param int $managementId
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function getReserveByParkId(int $managementId)
|
||||
{
|
||||
try {
|
||||
return DB::table('reserve')
|
||||
->join('park', 'reserve.park_id', '=', 'park.park_id')
|
||||
->where('park.management_id', $managementId)
|
||||
->where('reserve.valid_flag', 1)
|
||||
->select('reserve.reserve_id', 'reserve.park_id', 'reserve.ptype_id', 'reserve.psection_id')
|
||||
->get()
|
||||
->groupBy('park_id');
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " reserve データ取得失敗 management_id=" . $managementId . ", error=" . $e->getMessage());
|
||||
return collect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 駐輪場ごとの更新可能期間を取得(運営元フィルタ適用)
|
||||
*
|
||||
*
|
||||
* @param int $managementId
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function getParkGracePeriods(int $managementId)
|
||||
{
|
||||
try {
|
||||
return DB::table('park')
|
||||
->where('management_id', $managementId)
|
||||
->select(
|
||||
'park_id',
|
||||
'update_grace_period_start_date',
|
||||
'update_grace_period_start_time',
|
||||
'update_grace_period_end_date',
|
||||
'update_grace_period_end_time'
|
||||
)
|
||||
->get()
|
||||
->keyBy('park_id');
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 駐輪場更新可能期間取得失敗 management_id=" . $managementId . ", error=" . $e->getMessage());
|
||||
return collect();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 運営元が取り扱う車種一覧を取得
|
||||
*
|
||||
* マルチテナント対応のため、運営元ごとに表示する車種を可変にする。
|
||||
*
|
||||
* @param int $managementId
|
||||
* @return array
|
||||
*/
|
||||
private function getAvailableVehicles(int $managementId)
|
||||
{
|
||||
try {
|
||||
return DB::table('zone')
|
||||
->join('park', 'zone.park_id', '=', 'park.park_id')
|
||||
->leftJoin('psection', 'zone.psection_id', '=', 'psection.psection_id')
|
||||
->where('park.management_id', $managementId)
|
||||
->whereNotNull('psection.psection_subject')
|
||||
->select('psection.psection_subject')
|
||||
->distinct()
|
||||
->orderByRaw("FIELD(psection.psection_subject, '自転車', '原付', '自動二輪', '自動車')")
|
||||
->pluck('psection_subject')
|
||||
->toArray();
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("[ERROR] " . now()->format('Y-m-d H:i:s') . " 取り扱い車種取得失敗 management_id=" . $managementId . ", error=" . $e->getMessage());
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 駐輪場ごと・車種ごとの状態を計算
|
||||
*
|
||||
* @param \Illuminate\Support\Collection $parks
|
||||
* @param \Illuminate\Support\Collection $zones
|
||||
* @param \Illuminate\Support\Collection $reserve
|
||||
* @param \Illuminate\Support\Collection $parkGracePeriods
|
||||
* @param array $availableVehicles
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function calculateVehicleStatus($parks, $zones, $reserve, $parkGracePeriods, $availableVehicles)
|
||||
{
|
||||
$now = \Carbon\Carbon::now();
|
||||
|
||||
foreach ($parks as $park) {
|
||||
$park->vehicle_status = [];
|
||||
|
||||
foreach ($availableVehicles as $vehicle) {
|
||||
$zonesForType = ($zones[$park->park_id] ?? collect())->where('psection_subject', $vehicle);
|
||||
|
||||
// 空き台数計算
|
||||
$hasVacancy = false;
|
||||
foreach ($zonesForType as $zone) {
|
||||
$reserveCount = ($reserve[$park->park_id] ?? collect())
|
||||
->where('psection_id', $zone->psection_id)
|
||||
->where('ptype_id', $zone->ptype_id)
|
||||
->count();
|
||||
$vacancy = $zone->zone_tolerance - $zone->zone_number - $reserveCount;
|
||||
if ($vacancy > 0) {
|
||||
$hasVacancy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 猶予期間判定
|
||||
$grace = $parkGracePeriods[$park->park_id] ?? null;
|
||||
$inGrace = $this->isInGracePeriod($grace, $now);
|
||||
|
||||
// 状態判定
|
||||
if ($zonesForType->isEmpty() || !$grace) {
|
||||
$park->vehicle_status[$vehicle] = 'none';
|
||||
} elseif ($inGrace && $hasVacancy) {
|
||||
$park->vehicle_status[$vehicle] = 'available';
|
||||
} elseif (!$inGrace) {
|
||||
$park->vehicle_status[$vehicle] = 'out_of_period';
|
||||
} elseif (!$hasVacancy) {
|
||||
$park->vehicle_status[$vehicle] = 'waiting';
|
||||
} else {
|
||||
$park->vehicle_status[$vehicle] = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $parks;
|
||||
}
|
||||
|
||||
/**
|
||||
* 猶予期間内かどうかを判定
|
||||
*
|
||||
* @param object|null $grace
|
||||
* @param \Carbon\Carbon $now
|
||||
* @return bool
|
||||
*/
|
||||
private function isInGracePeriod($grace, $now)
|
||||
{
|
||||
if (!$grace) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// バリデーション
|
||||
if (
|
||||
!is_numeric($grace->update_grace_period_start_date) ||
|
||||
!preg_match('/^\d{1,2}:\d{2}$/', $grace->update_grace_period_start_time) ||
|
||||
!is_numeric($grace->update_grace_period_end_date) ||
|
||||
!preg_match('/^\d{1,2}:\d{2}$/', $grace->update_grace_period_end_time)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$year = $now->year;
|
||||
$month = $now->month;
|
||||
$startDay = (int)$grace->update_grace_period_start_date;
|
||||
$endDay = (int)$grace->update_grace_period_end_date;
|
||||
|
||||
if ($startDay > $endDay) {
|
||||
// 月またぎ(例: 25日~5日)
|
||||
$prevMonth = $now->copy()->subMonth();
|
||||
$startPrev = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $prevMonth->year, $prevMonth->month, $startDay, $grace->update_grace_period_start_time));
|
||||
$endCurr = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $year, $month, $endDay, $grace->update_grace_period_end_time));
|
||||
|
||||
$startCurr = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $year, $month, $startDay, $grace->update_grace_period_start_time));
|
||||
$nextMonth = $month == 12 ? 1 : $month + 1;
|
||||
$nextYear = $month == 12 ? $year + 1 : $year;
|
||||
$endNext = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $nextYear, $nextMonth, $endDay, $grace->update_grace_period_end_time));
|
||||
|
||||
return $now->between($startPrev, $endCurr) || $now->between($startCurr, $endNext);
|
||||
} else {
|
||||
// 同月(例: 5日~25日)
|
||||
$start = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $year, $month, $startDay, $grace->update_grace_period_start_time));
|
||||
$end = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $year, $month, $endDay, $grace->update_grace_period_end_time));
|
||||
|
||||
return $now->between($start, $end);
|
||||
}
|
||||
}
|
||||
|
||||
public function regulationCheck(Request $request)
|
||||
|
||||
@ -38,11 +38,11 @@ trait AuthenticatesUser
|
||||
|
||||
if ($saveIntended) {
|
||||
// ログイン後に元の画面に戻る
|
||||
return redirect()->guest(route('swo8_1', ['management_code' => $managementCode]));
|
||||
return redirect()->guest(route('login_input', ['management_code' => $managementCode]));
|
||||
} else {
|
||||
// ログイン後はマイページトップへ
|
||||
session()->forget('url.intended');
|
||||
return redirect()->route('swo8_1', ['management_code' => $managementCode]);
|
||||
return redirect()->route('login_input', ['management_code' => $managementCode]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,7 +17,6 @@ table.tablesorter tfoot tr th {
|
||||
}
|
||||
|
||||
table.tablesorter thead tr .header {
|
||||
background-image: url(bg.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center right;
|
||||
cursor: pointer;
|
||||
@ -34,14 +33,6 @@ table.tablesorter tbody tr.odd td {
|
||||
background-color: #F0F0F6;
|
||||
}
|
||||
|
||||
table.tablesorter thead tr .headerSortUp {
|
||||
background-image: url(asc.gif);
|
||||
}
|
||||
|
||||
table.tablesorter thead tr .headerSortDown {
|
||||
background-image: url(desc.gif);
|
||||
}
|
||||
|
||||
table.tablesorter thead tr .headerSortDown,
|
||||
table.tablesorter thead tr .headerSortUp {
|
||||
background-color: #8dbdd8;
|
||||
|
||||
@ -115,17 +115,26 @@ $(function () {
|
||||
});
|
||||
|
||||
// 駐輪場詳細ポップアップ
|
||||
$(document).on('click', '.btn-popup', function () {
|
||||
var parkId = $(this).data('park-id');
|
||||
$(document).on('click', '.btn-popup', function (e) {
|
||||
e.preventDefault();
|
||||
const url = $(this).data('url');
|
||||
|
||||
// data-url が存在しない場合はエラー
|
||||
if (!url) {
|
||||
console.error('data-url属性が設定されていません');
|
||||
alert('URLが取得できませんでした。');
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '/api/park-detail/' + parkId,
|
||||
url: url,
|
||||
method: 'GET',
|
||||
success: function (data) {
|
||||
$('#modalArea').html(data.html); // モーダル全体を挿入
|
||||
$('#parkDetailModal').modal('show'); // モーダルを表示
|
||||
success: function (response) {
|
||||
$('#modalArea').html(response.html);
|
||||
$('#popup-modal').modal('show');
|
||||
},
|
||||
error: function () {
|
||||
alert('詳細情報の取得に失敗しました');
|
||||
alert('詳細情報の取得に失敗しました。');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/typicons/2.0.9/typicons.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/earlyaccess/roundedmplus1c.css" rel="stylesheet">
|
||||
<link href="{{ asset('assets/css/mypage/slick.css') }}" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick-theme.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick-theme.css" />
|
||||
<link rel="stylesheet" href="{{ asset('assets/css/mypage/font-awesome.min.css') }}">
|
||||
<link href="{{ asset('assets/css/mypage/bootstrap.min.css') }}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="{{ asset('assets/css/mypage/picker.min.css') }}">
|
||||
@ -18,6 +18,7 @@
|
||||
<link href="{{ asset('assets/css/mypage/style.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('assets/css/mypage/jquery-confirm.min.css') }}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.4/jquery-confirm.min.css">
|
||||
@yield('head')
|
||||
<style>
|
||||
#main-news.jumbotron {
|
||||
@ -49,6 +50,20 @@
|
||||
<script src="{{ asset('assets/js/vendor/jquery.tablesorter/jquery.tablesorter.min.js') }}" type="text/javascript"></script>
|
||||
<script src="{{ asset('assets/js/commons.js') }}"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.4/jquery-confirm.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// モーダルを閉じる前にフォーカスを解除
|
||||
$('.modal').on('hide.bs.modal', function(e) {
|
||||
$(this).find(':focus').blur();
|
||||
});
|
||||
|
||||
// モーダルが完全に閉じた後、body にフォーカスを戻す
|
||||
$('.modal').on('hidden.bs.modal', function() {
|
||||
$('body').focus();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@yield('scripts')
|
||||
</body>
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ $management_code = $management ? $management->management_code : '';
|
||||
<li class="nav-item {{ $active_menu == 'SWC-8-1' ? 'active' : '' }}"><a class="nav-link" href="{{ route('regular_contract.create', ['management_code' => $management_code]) }}">新規定期契約</a></li>
|
||||
<li class="nav-item {{ $active_menu == 'SWC-11-1' ? 'active' : '' }}"><a class="nav-link" href="{{ route('park_waitlist.index', ['management_code' => $management_code]) }}">空き待ち状況確認</a></li>
|
||||
<li class="nav-item {{ $active_menu == 'SWC-10-1' ? 'active' : '' }}"><a class="nav-link" href="{{ route('park_search', ['management_code' => $management_code]) }}">駐輪場検索</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="{{ route('swo16_1', ['management_code' => $management_code]) }}" target="_blank">このページの使い方</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="{{ route('guide', ['management_code' => $management_code]) }}" target="_blank">このページの使い方</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
@extends('layouts.app')
|
||||
@section('title', $isRegularContract ? '空き駐輪場を確認する-新規定期契約 | So-Manager' : '駐輪場選択-駐輪場検索 | So-Manager')
|
||||
@section('content')
|
||||
<main>
|
||||
<header class="alert alert-success">
|
||||
<header class="title-header">
|
||||
@if($isRegularContract)
|
||||
<h4 class="container">新規定期契約 > 空き駐輪場を確認する</h4>
|
||||
新規定期契約 > 空き駐輪場を確認する
|
||||
@else
|
||||
<h4 class="container">駐輪場検索 > 駐輪場選択</h4>
|
||||
駐輪場検索 > 駐輪場選択
|
||||
@endif
|
||||
</header>
|
||||
<section id="" class="container mt20 mb20">
|
||||
@ -20,11 +21,11 @@
|
||||
<div class="w-100 alert alert-success">
|
||||
<h6><a class="text-success" data-toggle="collapse" href="#search-option" role="button"
|
||||
aria-expanded="false" aria-controls="search-option">絞込み条件を追加する</a></h6>
|
||||
<div class="collapse row" id="search-option">
|
||||
<div class="col-3">市町村名</div>
|
||||
<div class="collapse row show" id="search-option">
|
||||
<div class="col-3">市区町村名</div>
|
||||
<div class="col-9 mb10">
|
||||
<select id="city-select" name="city_id" class="form-control form-control-lg" onchange="this.form.submit()">
|
||||
<option value="">市町村を選択してください</option>
|
||||
<option value="">市区町村を選択してください</option>
|
||||
@foreach($cities as $city)
|
||||
<option value="{{ $city->city_id }}" @if(request('city_id')==$city->city_id) selected @endif>{{ $city->city_name }}</option>
|
||||
@endforeach
|
||||
@ -56,84 +57,35 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="header" style="cursor:default; pointer-events: none; background-color: #d4edda !important;">駐輪場名</th>
|
||||
<th class="header" style="cursor:default; pointer-events: none;">市町村名</th>
|
||||
<th class="header" style="cursor:default; pointer-events: none;">市区町村名</th>
|
||||
<th class="header" style="cursor:default; pointer-events: none;">駅名</th>
|
||||
<th class="header" style="cursor:default; pointer-events: none;">自転車</th>
|
||||
<th class="header" style="cursor:default; pointer-events: none;">原付</th>
|
||||
<th class="header" style="cursor:default; pointer-events: none;">自動二輪</th>
|
||||
<th class="header" style="cursor:default; pointer-events: none;">自動車</th>
|
||||
@foreach($available_vehicles as $vehicle)
|
||||
<th class="header" style="cursor:default; pointer-events: none;">{{ $vehicle }}</th>
|
||||
@endforeach
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($parks_table as $row)
|
||||
<tr>
|
||||
<td><a href="javascript:void(0);" class="btn-popup text-primary" data-park-id="{{ $row->park_id }}">
|
||||
<td><a href="javascript:void(0);"
|
||||
class="btn-popup text-primary"
|
||||
data-park-id="{{ $row->park_id }}"
|
||||
data-url="{{ url(session('management')->management_code . '/api/park-detail/' . $row->park_id) }}">
|
||||
{{ $row->park_name }}
|
||||
</a></td>
|
||||
<td>{{ $row->city_name }}</td>
|
||||
<td>{{ $row->station_neighbor_station }}</td>
|
||||
{{-- 自転車・原付・自動二輪・自動車列 --}}
|
||||
@foreach(['自転車', '原付', '自動二輪', '自動車'] as $vehicle)
|
||||
@foreach($available_vehicles as $vehicle)
|
||||
<td>
|
||||
@php
|
||||
$zonesForType = ($zones[$row->park_id] ?? collect())->where('psection_subject', $vehicle);
|
||||
// 空き台数計算
|
||||
$hasVacancy = false;
|
||||
foreach ($zonesForType as $zone) {
|
||||
$reserveCount = ($reserve[$row->park_id] ?? collect())
|
||||
->where('psection_id', $zone->psection_id)
|
||||
->where('ptype_id', $zone->ptype_id)
|
||||
->count();
|
||||
$vacancy = $zone->zone_tolerance - $zone->zone_number - $reserveCount;
|
||||
if ($vacancy > 0) {
|
||||
$hasVacancy = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 猶予期間判定
|
||||
$grace = $city_grace_periods[$row->city_id] ?? null;
|
||||
$gracePeriodValid =
|
||||
$grace &&
|
||||
is_numeric($grace->update_grace_period_start_date) &&
|
||||
preg_match('/^\d{1,2}:\d{2}$/', $grace->update_grace_period_start_time) &&
|
||||
is_numeric($grace->update_grace_period_end_date) &&
|
||||
preg_match('/^\d{1,2}:\d{2}$/', $grace->update_grace_period_end_time);
|
||||
|
||||
$inGrace = false;
|
||||
if ($gracePeriodValid) {
|
||||
$now = \Carbon\Carbon::now();
|
||||
$year = $now->year;
|
||||
$month = $now->month;
|
||||
$startDay = (int)$grace->update_grace_period_start_date;
|
||||
$endDay = (int)$grace->update_grace_period_end_date;
|
||||
if ($startDay > $endDay) {
|
||||
// 月またぎ
|
||||
// 前月の開始日~今月の終了日
|
||||
$prevMonth = $now->copy()->subMonth();
|
||||
$startPrev = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $prevMonth->year, $prevMonth->month, $startDay, $grace->update_grace_period_start_time));
|
||||
$endCurr = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $year, $month, $endDay, $grace->update_grace_period_end_time));
|
||||
// 今月の開始日~翌月の終了日
|
||||
$startCurr = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $year, $month, $startDay, $grace->update_grace_period_start_time));
|
||||
$nextMonth = $month == 12 ? 1 : $month + 1;
|
||||
$nextYear = $month == 12 ? $year + 1 : $year;
|
||||
$endNext = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $nextYear, $nextMonth, $endDay, $grace->update_grace_period_end_time));
|
||||
$inGrace = $now->between($startPrev, $endCurr) || $now->between($startCurr, $endNext);
|
||||
} else {
|
||||
// 同月
|
||||
$start = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $year, $month, $startDay, $grace->update_grace_period_start_time));
|
||||
$end = \Carbon\Carbon::createFromFormat('Y-m-d H:i', sprintf('%04d-%02d-%02d %s', $year, $month, $endDay, $grace->update_grace_period_end_time));
|
||||
$inGrace = $now->between($start, $end);
|
||||
}
|
||||
}
|
||||
$status = $row->vehicle_status[$vehicle] ?? 'none';
|
||||
@endphp
|
||||
@if ($zonesForType->isNotEmpty() && $gracePeriodValid)
|
||||
@if ($hasVacancy && $inGrace)
|
||||
<button class="btn btn-block btn-sm btn-outline-success btn_82-table btn-popup" data-park-id="{{ $row->park_id }}">定期契約</button>
|
||||
@elseif (!$inGrace)
|
||||
<button class="btn btn-block btn-sm btn-outline-danger btn_103-table btn-popup" data-park-id="{{ $row->park_id }}">販売期間外</button>
|
||||
@elseif (!$hasVacancy && $inGrace)
|
||||
<button class="btn btn-block btn-sm btn-outline-danger btn_103-table btn-popup" data-park-id="{{ $row->park_id }}">空き待ち申込</button>
|
||||
@endif
|
||||
@if($status === 'available')
|
||||
<button class="btn btn-block btn-sm btn-outline-success btn_82-table btn-popup" data-park-id="{{ $row->park_id }}" data-url="{{ url(session('management')->management_code . '/api/park-detail/' . $row->park_id) }}">定期契約</button>
|
||||
@elseif($status === 'out_of_period')
|
||||
<button class="btn btn-block btn-sm btn-outline-danger btn_103-table btn-popup" data-park-id="{{ $row->park_id }}" data-url="{{ url(session('management')->management_code . '/api/park-detail/' . $row->park_id) }}">販売期間外(予約可)</button>
|
||||
@elseif($status === 'waiting')
|
||||
<button class="btn btn-block btn-sm btn-outline-danger btn_103-table btn-popup" data-park-id="{{ $row->park_id }}" data-url="{{ url(session('management')->management_code . '/api/park-detail/' . $row->park_id) }}">空き待ち予約</button>
|
||||
@else
|
||||
<span class="text-muted"></span>
|
||||
@endif
|
||||
@ -142,7 +94,7 @@
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">該当する駐輪場はありません。</td>
|
||||
<td colspan="{{ 3 + count($available_vehicles) }}" class="text-center">該当する駐輪場はありません。</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
@ -180,11 +132,10 @@
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<div id="modalArea"></div>
|
||||
<div class="modal fade" id="popup-modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content" id="popup-content">
|
||||
<!-- Ajaxで詳細HTMLを挿入 -->
|
||||
<div class="modal fade" id="popup-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content" id="modalArea">
|
||||
<!-- Ajaxで取得したHTMLがここに挿入される -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
<!-- Bootstrapモーダル -->
|
||||
<div class="modal fade" id="parkDetailModal" tabindex="-1" aria-labelledby="parkDetailLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="parkDetailLabel">{{ $park->park_name }}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="閉じる">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!-- Googleマップ埋め込み -->
|
||||
<div style="width:100%; height:350px;">
|
||||
<iframe
|
||||
@ -41,12 +38,12 @@
|
||||
@endphp
|
||||
@foreach($zonesByPtype as $ptypeId => $zonesGroup)
|
||||
<div class="mb-3">
|
||||
<strong>{{ $zonesGroup->first()->ptype_subject }}</strong>
|
||||
<strong>{{ $zonesGroup->first()->ptype_subject }}{{ $zonesGroup->first()->zone_name }}</strong>
|
||||
<div style="display: flex; gap: 1em;">
|
||||
@foreach($zonesGroup as $zone)
|
||||
@php
|
||||
$vacant = $vacancyData[$zone->psection_id . '_' . $zone->ptype_subject] ?? 0;
|
||||
$grace = $city_grace_periods[$park->city_id] ?? null;
|
||||
$grace = $parkGracePeriod ?? null;
|
||||
$now = \Carbon\Carbon::now();
|
||||
|
||||
// 猶予期間判定
|
||||
@ -95,7 +92,7 @@
|
||||
data-park-id="{{ $park->park_id }}"
|
||||
data-psection-id="{{ $zone->psection_id }}"
|
||||
data-ptype-id="{{ $zone->ptype_id }}">
|
||||
空き待ち申込
|
||||
空き待ち予約
|
||||
</button>
|
||||
@endif
|
||||
@else
|
||||
@ -103,7 +100,7 @@
|
||||
data-park-id="{{ $park->park_id }}"
|
||||
data-psection-id="{{ $zone->psection_id }}"
|
||||
data-ptype-id="{{ $zone->ptype_id }}">
|
||||
販売期間外
|
||||
販売期間外(予約可)
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
@ -112,13 +109,7 @@
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">閉じる</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- jQuery Confirm用CSS/JS(jQuery本体は既に読み込まれていれば不要) -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.4/jquery-confirm.min.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-confirm/3.3.4/jquery-confirm.min.js"></script>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">閉じる</button>
|
||||
</div>
|
||||
Loading…
Reference in New Issue
Block a user