org.projectbuendia.client.ui.dialogs.OrderDialogFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.projectbuendia.client.ui.dialogs.OrderDialogFragment.java

Source

// Copyright 2015 The Project Buendia Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License.  You may obtain a copy
// of the License at: http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distrib-
// uted under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
// OR CONDITIONS OF ANY KIND, either express or implied.  See the License for
// specific language governing permissions and limitations under the License.

package org.projectbuendia.client.ui.dialogs;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.projectbuendia.client.R;
import org.projectbuendia.client.events.actions.OrderDeleteRequestedEvent;
import org.projectbuendia.client.events.actions.OrderSaveRequestedEvent;
import org.projectbuendia.client.models.Order;
import org.projectbuendia.client.utils.Utils;

import butterknife.ButterKnife;
import butterknife.InjectView;
import de.greenrobot.event.EventBus;

/** A {@link DialogFragment} for adding a new user. */
public class OrderDialogFragment extends DialogFragment {
    @InjectView(R.id.order_medication)
    EditText mMedication;
    @InjectView(R.id.order_dosage)
    EditText mDosage;
    @InjectView(R.id.order_frequency)
    EditText mFrequency;
    @InjectView(R.id.order_give_for_days)
    EditText mGiveForDays;
    @InjectView(R.id.order_give_for_days_label)
    TextView mGiveForDaysLabel;
    @InjectView(R.id.order_duration_label)
    TextView mDurationLabel;
    @InjectView(R.id.order_delete)
    Button mDelete;
    private LayoutInflater mInflater;

    /** Creates a new instance and registers the given UI, if specified. */
    public static OrderDialogFragment newInstance(String patientUuid, Order order) {
        Bundle args = new Bundle();
        args.putString("patientUuid", patientUuid);
        args.putBoolean("new", order == null);

        // This time is used as the current time for any calculations in this dialog.
        // Use this value throughout instead of calling now().  This is necessary to maintain UI
        // consistency (e.g. if the dialog is opened before midnight and submitted after midnight).
        args.putLong("now_millis", DateTime.now().getMillis());

        if (order != null) {
            args.putString("uuid", order.uuid);
            args.putString("instructions", order.instructions);
            args.putLong("start_millis", order.start.getMillis());
            if (order.stop != null) {
                args.putLong("stop_millis", order.stop.getMillis());
            }
        }
        OrderDialogFragment fragment = new OrderDialogFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mInflater = LayoutInflater.from(getActivity());
    }

    @Override
    public void onResume() {
        super.onResume();
        // Replace the existing button listener so we can control whether the dialog is dismissed.
        final AlertDialog dialog = (AlertDialog) getDialog();
        dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onSubmit(dialog);
            }
        });
    }

    private void populateFields(Bundle args) {
        String instructions = args.getString("instructions");
        mMedication.setText(Order.getMedication(instructions));
        mDosage.setText(Order.getDosage(instructions));
        mFrequency.setText(Order.getFrequency(instructions));
        DateTime now = Utils.getDateTime(args, "now_millis");
        Long stopMillis = Utils.getLong(args, "stop_millis");
        if (stopMillis != null) {
            LocalDate lastDay = new DateTime(stopMillis).toLocalDate();
            int days = Days.daysBetween(now.toLocalDate(), lastDay).getDays();
            if (days >= 0) {
                mGiveForDays.setText("" + (days + 1)); // 1 day means stop after today
            }
        }
        updateLabels();
    }

    public void onSubmit(Dialog dialog) {
        String uuid = getArguments().getString("uuid");
        String patientUuid = getArguments().getString("patientUuid");
        String medication = mMedication.getText().toString().trim();
        String dosage = mDosage.getText().toString().trim();
        String frequency = mFrequency.getText().toString().trim();

        String instructions = Order.getInstructions(medication, dosage, frequency);
        String durationStr = mGiveForDays.getText().toString().trim();
        Integer durationDays = durationStr.isEmpty() ? null : Integer.valueOf(durationStr);
        boolean valid = true;
        if (medication.isEmpty()) {
            setError(mMedication, R.string.enter_medication);
            valid = false;
        }
        if (durationDays != null && durationDays == 0) {
            setError(mGiveForDays, R.string.order_give_for_days_cannot_be_zero);
            valid = false;
        }
        Utils.logUserAction("order_submitted", "valid", "" + valid, "uuid", uuid, "medication", medication,
                "dosage", dosage, "frequency", frequency, "instructions", instructions, "durationDays",
                "" + durationDays);

        if (!valid) {
            return;
        }

        dialog.dismiss();

        DateTime now = Utils.getDateTime(getArguments(), "now_millis");
        DateTime start = Utils.getDateTime(getArguments(), "start_millis");
        start = Utils.valueOrDefault(start, now);

        if (durationDays != null) {
            // Adjust durationDays to account for a start date in the past.  Entering "2"
            // always means two more days, stopping after tomorrow, regardless of start date.
            LocalDate firstDay = start.toLocalDate();
            LocalDate lastDay = now.toLocalDate().plusDays(durationDays - 1);
            durationDays = Days.daysBetween(firstDay, lastDay).getDays() + 1;
        }

        // Post an event that triggers the PatientChartController to save the order.
        EventBus.getDefault()
                .post(new OrderSaveRequestedEvent(uuid, patientUuid, instructions, start, durationDays));
    }

    public void onDelete(Dialog dialog, final String orderUuid) {
        dialog.dismiss();

        new AlertDialog.Builder(getActivity()).setMessage(R.string.confirm_order_delete)
                .setTitle(R.string.title_confirmation)
                .setPositiveButton(R.string.delete, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int i) {
                        EventBus.getDefault().post(new OrderDeleteRequestedEvent(orderUuid));
                    }
                }).setNegativeButton(R.string.cancel, null).create().show();
    }

    private void setError(EditText field, int resourceId) {
        field.setError(getResources().getString(resourceId));
        field.invalidate();
        field.requestFocus();
    }

    @Override
    public @NonNull Dialog onCreateDialog(Bundle savedInstanceState) {
        View fragment = mInflater.inflate(R.layout.order_dialog_fragment, null);
        ButterKnife.inject(this, fragment);
        mGiveForDays.addTextChangedListener(new DurationDaysWatcher());

        Bundle args = getArguments();
        boolean newOrder = args.getBoolean("new");
        String title = getString(newOrder ? R.string.title_new_order : R.string.title_edit_order);
        final String orderUuid = args.getString("uuid");
        populateFields(args);

        final Dialog dialog = new AlertDialog.Builder(getActivity()).setCancelable(false) // Disable auto-cancel.
                .setTitle(title)
                // The positive button uses dialog, so we have to set it below, after dialog is assigned.
                .setNegativeButton(R.string.cancel, null).setView(fragment).create();

        ((AlertDialog) dialog).setButton(Dialog.BUTTON_POSITIVE, getResources().getString(R.string.ok),
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        onSubmit(dialog);
                    }
                });

        mDelete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onDelete(dialog, orderUuid);
            }
        });

        // Hide or show the "Stop" and "Delete" buttons appropriately.
        Long stopMillis = Utils.getLong(args, "stop_millis");
        Long nowMillis = Utils.getLong(args, "now_millis");
        Utils.showIf(mDelete, !newOrder);

        // Open the keyboard, ready to type into the medication field.
        dialog.getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_VISIBLE);
        mMedication.requestFocus();
        return dialog;
    }

    /** Updates the various labels in the form that react to changes in input fields. */
    void updateLabels() {
        DateTime now = Utils.getDateTime(getArguments(), "now_millis");
        String text = mGiveForDays.getText().toString().trim();
        int days = text.isEmpty() ? 0 : Integer.parseInt(text);
        LocalDate lastDay = now.toLocalDate().plusDays(days - 1);
        mGiveForDaysLabel.setText(days == 0 ? R.string.order_give_for_days
                : days == 1 ? R.string.order_give_for_day : R.string.order_give_for_days);
        mDurationLabel.setText(getResources()
                .getString(days == 0 ? R.string.order_duration_unspecified
                        : days == 1 ? R.string.order_duration_stop_after_today
                                : days == 2 ? R.string.order_duration_stop_after_tomorrow
                                        : R.string.order_duration_stop_after_date)
                .replace("%s", Utils.toShortString(lastDay)));
    }

    class DurationDaysWatcher implements TextWatcher {
        @Override
        public void beforeTextChanged(CharSequence c, int x, int y, int z) {
        }

        @Override
        public void onTextChanged(CharSequence c, int x, int y, int z) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            updateLabels();
        }
    }
}