0

I have a ScheduleController that gets the start_time and end_time from the schedules table.

ScheduleController

$schedules = Schedule::select('start_time', 'end_time')
    ->where('weekday', $request->input('weekday'))
    ->get()
    ->toArray();

$collection = collect($schedules)->map(function ($time) {
    return [date("g:i", strtotime($time['start_time'])), date("g:i", strtotime($time['end_time']))];
})->flatten();

$data = $collection->values()->all();

// the $data above produce something like this
['6:30', '7:30'],
['11:30', '12:30']

I'm getting the array response from my ScheduleController, and in my blade file I have a BootStrap DateTimePicker, this DateTimePicker will use the array response in disabledTimeIntervals.

The syntax of disabledTimeIntervals looks like the code below, the hour and minutes are hard coded here:

// example
disabledTimeIntervals: [
    [ moment({ hour: 17, minute: 30 }), moment({ hour: 18, minute: 30 }) ]
],

The question is, How can I format the array response from my ScheduleController to be like this:

// FROM
['6:30', '7:30'],
['11:30', '12:30']

// TO
[ moment({ hour: 6, minute: 30 }), moment({ hour: 7, minute: 30 }) ],
[ moment({ hour: 11, minute: 30 }), moment({ hour: 12, minute: 30 }) ]

EDIT

I tried Mtdt 's answer, but it's not disabling the hour and minutes if I put multiple arrays, but in the single array it works, See the example below, I manually add it to the code.

const stringToDate = (dateString) => {
    const [hours, minutes] = dateString.split(':');
    return moment().hours(hours).minutes(minutes);
}
const formatDates = datesToFormat => datesToFormat.map(dateString => {
    if (Array.isArray(dateString)) {
        return dateString.map(s => stringToDate(s));
    } else {
        return stringToDate(dateString);
    }
})

let customOptions = {
    format: 'hh:mm A',
    disabledTimeIntervals: [
        // not working in multiple array 
        formatDates([ ['6:30', '7:30'], ['11:30', '12:30'] ])

        // this one works if single array and not enclosed with []
        formatDates(['6:30', '7:30'])
    ],
}

$('.timepicker').datetimepicker(customOptions)

Maybe it's not formatted like below?

disabledTimeIntervals: [
    [moment({ hour:6, minute:30 }), moment({ hour:7, minute:30 })],
    [moment({ hour:11, minute:30 }), moment({ hour:12, minute:30 })]
],

This is the result when I console.log(formatDates([['6:30', '7:30'], ['11:30', '12:30']]))

enter image description here


EDIT #2

I tried doing it the PHP way, but there are still some problems I'm facing.

My problem now is removing the quotes (") in the array result and the extra comma (,) at the end. Currently, I have str_replace('"', "", 'string-here') but it's not removing the quotes.

My code

$user = User::find(1);
$schedules = Schedule::select('start_time', 'end_time')
    ->whereBelongsTo($user)
    ->where('weekday', 1)
    ->get()
    ->toArray();

$collection = collect($schedules)->map(function ($time) {
    return [date("g:i", strtotime($time['start_time'])), date("g:i", strtotime($time['end_time']))];
});

$data = $collection->values()->all();

// $data produces this result
// [
//   [
//     "6:45",
//     "7:45",
//   ],
//   [
//     "10:30",
//     "11:30",
//   ],
// ]

$carrier = [];

foreach ($data as $key => $a) {
    $detail1 = preg_split('/:/i', $a[0]);
    $detail2 = preg_split('/:/i', $a[1]);

    array_push($carrier, array(str_replace('"', "", 'moment({ hour:'.$detail1[0].', minute:'.$detail1[1].' }), moment({ hour:'.$detail2[0].', minute:'.$detail2[1].' })')));
}

return $carrier;
// currently this is what I got as the result when I return $carrier
[
  [
    "moment({ hour:6, minute:45 }), moment({ hour:7, minute:45 })",
  ],
  [
    "moment({ hour:10, minute:30 }), moment({ hour:11, minute:30 })",
  ],
]

// and I want to remove the quotes " and the extra comma , at the end of the string
// so this is the final form
[
  [
    moment({ hour:6, minute:45 }), moment({ hour:7, minute:45 })
  ],
  [
    moment({ hour:10, minute:30 }), moment({ hour:11, minute:30 })
  ],
]

5
  • Rather make it momented on the frontend? Commented Oct 24, 2022 at 13:42
  • @nice_dev sorry, I didn't get what you mean, can you elaborate more? Commented Oct 24, 2022 at 13:44
  • @nice_dev I mean, if we can momented it on frontend? yes Commented Oct 24, 2022 at 13:52
  • So you can add the moment call in your frontend in the ajax response instead of returning a ready made string from the controller. Commented Oct 24, 2022 at 13:54
  • I mean as of now, I don't know how can I separate for example ['6:30'] to moment({ hour: 6, minute: 30 }) Commented Oct 24, 2022 at 13:55

1 Answer 1

1

To have a moment object as you desire:

moment().hours(6).minutes(30).seconds(0)   

A complete script:

const datesToFormat = ['6:30', '7:30'];
const formattedDates = datesToFormat.map(dateString => {
 const [hours, minutes] = dateString.split(':');
 return moment().hours(hours).minutes(minutes).seconds(0)
})

Read the docs: https://momentjs.com/docs/#/get-set/


EDIT for multilevel array

const stringToDate = (dateString) => {
  const [hours, minutes] = dateString.split(':');
  return moment().hours(hours).minutes(minutes).seconds(0);
}
const formatDates = datesToFormat => datesToFormat.map(dateString => {
 if (Array.isArray(dateString)) {
   return dateString.map(s => stringToDate(s));
 } else {
   return stringToDate(dateString);
 }
})
formatDates(["6:30", "7:30"])
formatDates([["6:30", "7:30"], ["8:30", "9:30"]])
Sign up to request clarification or add additional context in comments.

10 Comments

I'll try this one, thank you for providing an answer @Mtdt
Result of testing: I tried and it's working fine for a single array, there's a problem when I make it['6:30', '7:30'], ['11:30', '12:30'] just like in the question. Invalid destructuring assignment target
add a condition, the split() works on string, not array, if you have multilevel array adapt it to your needs, with recursion or however you prefer.
added a solution for a response withouth recursion and only for array with maximum 2 level
To test it you can use the javascript console (ctrl+shif+i or f12) copy all code an paste it on moment.js page (it has loaded moment.js library). The method map() is a loop, I don't know exactly what you need to do, the example I posted already loop on and array. Try to break it a little bit and rewrite to fit your needs.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.