@@ -514,6 +514,18 @@ protected function handleMenuPostback(string $lineUserId, array $params, FreshMa
514514 'chat_ai ' => $ this ->enterAIChatMode ($ conversation ),
515515 'help ' => $ this ->handleCommand ('help ' , $ lineUserId , $ conversation , []),
516516 'back_to_menu ' => $ this ->buildGreetingWithButtons ($ conversation ),
517+
518+ // ===== Rider Registration: ประเภทไรเดอร์ =====
519+ 'rider_type_delivery ' => $ this ->handleRiderRegister_Text ($ conversation , '1 ' , []),
520+ 'rider_type_service ' => $ this ->handleRiderRegister_Text ($ conversation , '2 ' , []),
521+ 'rider_type_both ' => $ this ->handleRiderRegister_Text ($ conversation , '3 ' , []),
522+
523+ // ===== Rider Registration: หมวดหมู่งาน =====
524+ 'rider_cat_fresh ' => $ this ->handleRiderCategory_Text ($ conversation , '1 ' , []),
525+ 'rider_cat_food ' => $ this ->handleRiderCategory_Text ($ conversation , '2 ' , []),
526+ 'rider_cat_doc ' => $ this ->handleRiderCategory_Text ($ conversation , '3 ' , []),
527+ 'rider_cat_all ' => $ this ->handleRiderCategory_Text ($ conversation , '4 ' , []),
528+
517529 default => $ this ->buildGreetingWithButtons ($ conversation ),
518530 };
519531 }
@@ -583,6 +595,9 @@ protected function dispatchByState(FreshMarketConversation $conversation, string
583595 'search_browsing:location ' => $ this ->handleSearchLocation_Location ($ conversation , $ inputData ['lat ' ], $ inputData ['lng ' ], $ extra ),
584596
585597 // === ORDER FLOW ===
598+ 'order_select:text ' => $ this ->handleOrderSelect_Text ($ conversation , $ inputData , $ extra ),
599+ 'order_select:image ' => $ this ->handleWrongInputType ($ conversation , 'image ' ),
600+ 'order_select:location ' => $ this ->handleOrderQuantity_Location ($ conversation , $ inputData ['lat ' ] ?? 0 , $ inputData ['lng ' ] ?? 0 , $ extra ),
586601 'order_quantity:text ' => $ this ->handleOrderQuantity_Text ($ conversation , $ inputData , $ extra ),
587602 'order_quantity:location ' => $ this ->handleOrderQuantity_Location ($ conversation , $ inputData ['lat ' ], $ inputData ['lng ' ], $ extra ),
588603 'order_quantity:image ' => $ this ->handleWrongInputType ($ conversation , 'image ' ),
@@ -597,6 +612,11 @@ protected function dispatchByState(FreshMarketConversation $conversation, string
597612 'search_location:image ' => $ this ->handleWrongInputType ($ conversation , 'image ' ),
598613 'search_browsing:image ' => $ this ->handleWrongInputType ($ conversation , 'image ' ),
599614
615+ // === LISTING COMPLETE (ลงขายเสร็จ → กลับ idle อัตโนมัติ) ===
616+ 'listing_complete:text ' => $ this ->handleCompletedState_Text ($ conversation , $ inputData , $ extra ),
617+ 'listing_complete:image ' => $ this ->handleCompletedState_Text ($ conversation , '' , $ extra ),
618+ 'listing_complete:location ' => $ this ->handleCompletedState_Text ($ conversation , '' , $ extra ),
619+
600620 // === RIDER REGISTRATION FLOW ===
601621 'rider_register:text ' => $ this ->handleRiderRegister_Text ($ conversation , $ inputData , $ extra ),
602622 'rider_register:image ' => $ this ->handleWrongInputType ($ conversation , 'image ' ),
@@ -605,6 +625,11 @@ protected function dispatchByState(FreshMarketConversation $conversation, string
605625 'rider_category:image ' => $ this ->handleWrongInputType ($ conversation , 'image ' ),
606626 'rider_category:location ' => $ this ->handleWrongInputType ($ conversation , 'location ' ),
607627
628+ // === RIDER COMPLETE (สมัครเสร็จ → กลับ idle อัตโนมัติ) ===
629+ 'rider_complete:text ' => $ this ->handleCompletedState_Text ($ conversation , $ inputData , $ extra ),
630+ 'rider_complete:image ' => $ this ->handleCompletedState_Text ($ conversation , '' , $ extra ),
631+ 'rider_complete:location ' => $ this ->handleCompletedState_Text ($ conversation , '' , $ extra ),
632+
608633 // === DEFAULT ===
609634 default => $ this ->handleWrongInputType ($ conversation , $ inputType ),
610635 };
@@ -1270,6 +1295,63 @@ protected function handleSearchBrowsing_Text(FreshMarketConversation $conversati
12701295 // ║ BUYER ORDER FLOW HANDLERS ║
12711296 // ╚══════════════════════════════════════════╝
12721297
1298+ /**
1299+ * order_select + text → ผู้ใช้พิมพ์ข้อความขณะเลือกสินค้า
1300+ *
1301+ * ถ้าเป็นตัวเลข → พยายาม match กับ listing จากผลค้นหาล่าสุด
1302+ * ถ้าเป็นข้อความ → ค้นหาใหม่ด้วย query
1303+ */
1304+ protected function handleOrderSelect_Text (FreshMarketConversation $ conversation , string $ message , array $ extra ): array
1305+ {
1306+ $ searchCtx = $ conversation ->getFlowContext ('search ' );
1307+ $ listingIds = $ searchCtx ['result_listing_ids ' ] ?? [];
1308+
1309+ // ถ้าพิมพ์ตัวเลข → ลอง match กับ listing
1310+ $ msg = trim ($ message );
1311+ if (is_numeric ($ msg )) {
1312+ $ index = (int ) $ msg - 1 ;
1313+ if (isset ($ listingIds [$ index ])) {
1314+ $ listing = FreshMarketListing::find ($ listingIds [$ index ]);
1315+ if ($ listing && $ listing ->isAvailableForPurchase ()) {
1316+ // เริ่ม order flow เหมือน postback
1317+ $ conversation ->transitionTo (FreshMarketConversation::STATE_ORDER_QUANTITY , [
1318+ 'order ' => [
1319+ 'listing_id ' => $ listing ->id ,
1320+ 'listing_title ' => $ listing ->title ,
1321+ 'listing_price ' => $ listing ->price ,
1322+ 'listing_unit ' => $ listing ->unit ,
1323+ 'seller_shop_name ' => $ listing ->seller ?->shop_name ?? 'ร้านค้า ' ,
1324+ 'started_at ' => now ()->toIso8601String (),
1325+ ],
1326+ ]);
1327+
1328+ $ progress = $ conversation ->getProgressText ();
1329+
1330+ return [
1331+ 'text ' => "{$ progress }\n\n🛒 {$ listing ->title }\n💰 ฿ " . number_format ($ listing ->price , 0 ) . " / {$ listing ->unit }\n\nจะสั่งกี่ {$ listing ->unit } คะ? \nนัดรับเองหรือให้ส่ง? " ,
1332+ ];
1333+ }
1334+ }
1335+ }
1336+
1337+ // ถ้ามีพิกัดเดิม → ค้นหาด้วย query ใหม่
1338+ if ($ conversation ->last_search_latitude ) {
1339+ return $ this ->searchNearbyAndRespond (
1340+ $ conversation ,
1341+ (float ) $ conversation ->last_search_latitude ,
1342+ (float ) $ conversation ->last_search_longitude ,
1343+ ['query ' => $ message ]
1344+ );
1345+ }
1346+
1347+ // ไม่มีพิกัด → แนะนำส่งตำแหน่ง
1348+ $ conversation ->transitionTo (FreshMarketConversation::STATE_SEARCH_LOCATION );
1349+
1350+ return [
1351+ 'text ' => "📍 ส่งตำแหน่งมาเพื่อค้นหา \"{$ message }\" ใกล้บ้านค่ะ " ,
1352+ ];
1353+ }
1354+
12731355 /**
12741356 * order_quantity + text → AI parse จำนวนและวิธีรับ
12751357 */
@@ -1908,6 +1990,32 @@ protected function handleRiderRejectJobPostback(string $lineUserId, array $param
19081990 ];
19091991 }
19101992
1993+ // ╔══════════════════════════════════════════╗
1994+ // ║ COMPLETED STATE HANDLER ║
1995+ // ╚══════════════════════════════════════════╝
1996+
1997+ /**
1998+ * listing_complete / rider_complete + any input
1999+ *
2000+ * สถานะ "เสร็จ" เหล่านี้ควรถูก reset ไป idle แล้ว
2001+ * แต่ถ้าเกิด race condition หรือผู้ใช้ส่งข้อความเร็วมาก
2002+ * ก็ reset ให้อัตโนมัติแล้วเริ่มต้นใหม่
2003+ */
2004+ protected function handleCompletedState_Text (FreshMarketConversation $ conversation , mixed $ input , array $ extra ): array
2005+ {
2006+ $ conversation ->resetToIdle ();
2007+
2008+ // ถ้ามีข้อความ → ลอง dispatch ใหม่ใน idle
2009+ if (is_string ($ input ) && ! empty (trim ($ input ))) {
2010+ $ command = $ this ->detectCommand ($ input );
2011+ if ($ command ) {
2012+ return $ this ->handleCommand ($ command , $ conversation ->line_user_id , $ conversation , $ extra );
2013+ }
2014+ }
2015+
2016+ return $ this ->buildGreetingWithButtons ($ conversation );
2017+ }
2018+
19112019 // ╔══════════════════════════════════════════╗
19122020 // ║ HELPER: LISTING CREATION ║
19132021 // ╚══════════════════════════════════════════╝
0 commit comments