Hướng phát triển

Một phần của tài liệu đồ án tốt nghiệp ứng dụng quản lý phòng trọ (Trang 135 - 159)

➢Tiếp tục phát triển sang hệ điều hành IOS.

➢Tối ưu hóa quá trình truyền tải và hiển thị, giảm thời gian tải dữ liệu từ máy chủ Firebase về hệ thống.

Tài liệu tham khảo

Tiếng Việt:

1. Tran Van Canh. Scan QR/Barcode với ZXing Android Embedded (journeyapps/zxing-

android-embedded) trong Android, 19/12/2020, https://viblo.asia/p/scan-qrbarcode-voi-zxing- android-embedded-journeyappszxing-android-embedded-trong-android-924lJqWWZPM

2. Thắng Cảnh. Dân số thành phố Vũng Tàu là 351.300 người với

101.347 hộ,

15/12/2020,http://vungtau.baria-vungtau.gov.vn/web/guest/tin-

tuc/- /brvt/extAssetPublisher/content/8857902/dan-so-thanh-pho-vung-tau-la-351- 300-nguoi-voi- 101-347-ho

3. Nguyen Minh Duong. Tạo ứng dụng QR code Scanner nhanh chóng với thư viện ZXING,

19/12/2020,https://viblo.asia/p/tao-ung-dung-qr-code-scanner-nhanh-chong-voi-thu- vien- zxing-ORNZqPp3K0n

4. Đỗ Đức Đình Đạt. Firebase là gì? Giải pháp lập trình không cần Backend từ

Google, 18/12/2020,https://wiki.matbao.net/firebase-la-gi-giai-phap-lap-trinh-khong-can- backend-tu- google/#firebase-la-gi 5. Anroid (hệ điều hành), 16/12/2020, https://vi.wikipedia.org/wiki/Android_(h%E1%BB%87_%C4%91i%E1%BB%81u_h%C3% A0nh) 6. Kotlin (ngôn ngữ lập trình), 16/12/2020, https://vi.wikipedia.org/wiki/Kotlin_(programming_language)

7. Vũ Hoàng Lâm Nhi (2020), Xây dựng hệ thống quản lý bảo dưỡng, sửa chữa thiết

bị cho doanh nghiệp – IziSolution, Đồ án, trường Đại Học Bà Rịa Vũng Tàu, Vũng Tàu

8. Nguyễn Mạnh Quân. Cùng tìm hiểu về Kotlin (Phần 1), 16/12/2020,

https://viblo.asia/p/cung-tim-hieu-ve-kotlin-phan-2-924lJMDXZPM 9. Nguyễn Ngọc Trung. Kotlin và Java: kế thừa và phát triển, 17/12/2020, https://codecungtrung.com/kotlin/kotlin-va-java/ 10. Trần Duy Trưởng. Tổng quan về Kotlin, 17/12/2020, https://labs.septeni- technology.jp/android-2/tong-quan-ve-kotlin/ 11. David Xuân. Giới thiệu mọi thứ về Firebase của Google, 18/12/2020,

12. Nguyen Thi Tu Yen. MPAndroidChart and Example, 20/12/2020,

https://viblo.asia/p/mpandroidchart-and-example-Az45badzlxY Tiếng Anh:

1. Rkistner. ZXing Android Embedded, 19/12/2020,

https://github.com/journeyapps/zxing- android-embedded

2. Philipp Jahoda. MPAndroidChart, 20/12/2020,

Phụ lục

Phụ lục A. Cấu trúc ứng dụng Motel Management

Hình phụ lục 1. Cấu trúc chung của ứng dụng Motel Management

Bảng phụ lục 1. Bảng mô tả cấu trúc thư mục con của hình phụ lục 2 STT Tên thư mục 1 adapters 2 anim 3 common 4 event 5 firebase 6 fragment 7 models 8 motelroomtt 9 others 10 view

Code của class BillAdapter, các class CartAdapter, LodgerAdapter, RoomAdapter, ServiceAdapter, ChooseImageServiceAdapter xử lý tương tự:

class BillAdapter(var listBill: ArrayList<Bill>):

RecyclerView.Adapter<RecyclerView.ViewHolder>() {

companion object{

const val SECTION_VIEW = 0

const val CONTENT_VIEW = 1

const val LOADING_VIEW = -1

}

public var isAll=false private var mValid = true

private val mSections: SparseArray<Section> = SparseArray<Section>()

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder

{

return if (viewType === LOADING_VIEW) { LoadingViewHolder(

LayoutInflater.from(parent.context)

.inflate(R.layout.item_load_more, parent, false) )

} else {

if (viewType === SECTION_VIEW ) { SectionHeaderViewHolder(

LayoutInflater.from(parent.context)

.inflate(R.layout.item_header_rv_bill, parent, false) )

} else ItemViewHolder(

LayoutInflater.from(parent.context).inflate(R.layout.item_rv_bill, parent,

false),

parent.context

) } }

fun addItems(listBillNew: ArrayList<Bill>){

listBill.addAll(listBillNew) notifyDataSetChanged() }

override fun getItemViewType(position: Int): Int {

return if (listBill[position].id.isEmpty()) {

LOADING_VIEW

} else {

if (listBill[position]._isSection) {

SECTION_VIEW } else { CONTENT_VIEW } } } fun addLoading(){ listBill.add(Bill())

notifyItemInserted(listBill.size - 1) }

fun removeLoading() {

if (listBill.size==0){

return

}

val position: Int = listBill.size - 1

val item: Bill = getItem(position)

if (item != null&&item.id.isEmpty()) {

listBill.removeAt(position) notifyItemRemoved(position) }

}

private fun getItem(position: Int): Bill {

return listBill[position] }

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { if

(SECTION_VIEW == getItemViewType(position)) {

SectionHeaderViewHolder

val sectionItem: Bill = listBill[position]

val date:String=MyString.convertLongToTime(sectionItem.createDateBill, "MM/yyyy")

sectionHeaderViewHolder.txtMonthBill.text ="Month ".plus(date)

var total:Double =0.0

var count:Int=0

val listBillAll= if(!isAll) {

SplashScreenActivity.listBills.filter{ p->p.roomId==sectionItem.roomId} }

else{

SplashScreenActivity.listBills

}

for (bill:Bill in listBillAll ){

val dateBill:String=MyString.convertLongToTime(bill.createDateBill, "MM/yyyy")

if (!bill._isSection && dateBill == date){

total+=bill.total count++ }

}

sectionHeaderViewHolder.txtTotal.text = MyString.convertNumberFormat("%,.0f",

total).plus(

"đ" )

sectionHeaderViewHolder.txtTotalBill.text=MyString.convertNumberFormat("%,d",

count).plus( " bill" ) return } if (LOADING_VIEW == getItemViewType(position)) { return }

val itemViewHolder:ItemViewHolder = holder as ItemViewHolder val currentBill: Bill = listBill[position]

val room:Room = (SplashScreenActivity.listRooms.filter{ p->p.id ==currentBill.roomId

})[0]

itemViewHolder.txtBillName.text = currentBill.billName itemViewHolder.txtRoomName.text = room.roomName

itemViewHolder.txtCreateDateBill.text = MyString.convertLongToTime(

currentBill.createDateBill, "MM/yyyy HH:mm" )

if (currentBill.dateOfPayment==0L){

itemViewHolder.txtBillStatus.setTextColor(Color.RED)

itemViewHolder.txtBillStatus.text="Unpaid" }else{

itemViewHolder.txtBillStatus.setTextColor(Color.BLACK)

itemViewHolder.txtBillStatus.text="Paid" }

val totalBill:ArrayList<DetailBill> = SplashScreenActivity.listDetailBills.filter{ p- >p.billId==currentBill.id} as ArrayList<DetailBill>

if (totalBill.size==1){

val context=itemViewHolder.itemView.context

val service: Service = ( SplashScreenActivity.listServices.filter

>p.id==totalBill[0].serviceId })[0]

val uri:String = "@drawable/".plus(service.imageName)

(without the extension) is the file

var imageResource:Int = context.resources.getIdentifier(uri, null context.packageName)

val res: Drawable = context.resources.getDrawable(imageResource itemViewHolder.imgIconBill.setImageDrawable(res)

}else{

itemViewHolder.imgIconBill.setImageResource(R.drawable.ic_bill

}

itemViewHolder.txtTotalBill.text=MyString.convertNumberFormat("%,.0f"

currentBill.total).plus( "đ" )

itemViewHolder.itemView.setOnClickListener {

var intent=Intent(itemViewHolder.itemView.context, DetailBillActivity intent.putExtra("BillSelected", currentBill)

itemViewHolder.itemView.context.startActivity(intent)

itemViewHolder.itemView.setOnLongClickListener {

/ f.onBind()

f.show(

(it?.context as FragmentActivity).supportFragmentManager, f.tag

)

true

}

}

private fun getTotalMonth (date: String): Double {

var total:Double=0.0

for (bill:Bill in listBill){

val dateBill:String=MyString.convertLongToTime(bill.createDateBill, "MM/yyyy")

if (!bill._isSection && dateBill == date){

total+=bill.total

} }

return total

}

override fun getItemCount(): Int {

return listBill.size

}

fun clear() {

listBill.clear()

notifyDataSetChanged() }

class LoadingViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

var progressBar: ProgressBar init {

progressBar=itemView.findViewById(R.id.progressBar) }

}

class ItemViewHolder(itemView: View, context: Context?) :

RecyclerView.ViewHolder(itemView) {

var txtBillName: TextView var txtCreateDateBill:TextView var txtBillStatus:TextView var txtTotalBill:TextView var txtRoomName:TextView var imgIconBill:ImageView init {

txtBillName = itemView.findViewById(R.id.txtBillName)

txtCreateDateBill = itemView.findViewById(R.id.txtCreateDateBill)

txtBillStatus = itemView.findViewById(R.id.txtBillStatus )

txtTotalBill = itemView.findViewById(R.id.txtTotalBill )

txtRoomName = itemView.findViewById(R.id.txtRoomName)

imgIconBill = itemView.findViewById(R.id.imgIconBill) }

}

class SectionHeaderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

var txtMonthBill: TextView var txtTotal:TextView var txtTotalBill:TextView init {

txtMonthBill = itemView.findViewById(R.id.txtMonthBill)

txtTotal = itemView.findViewById(R.id.txtTotal)

txtTotalBill = itemView.findViewById(R.id.txtTotalBill) }

}

class Section(var firstPosition: Int, var title: CharSequence) { var sectionedPosition = 0

} }

Hình phụ lục 4. Cấu trúc thư mục anim

Trong thư mục này gồm có hai class BaseViewAnimator, ZoomInDownAnimator. Hai class này có ý nghĩa lần lượt là class trừu tượng hiệu ứng, class còn lại là class định nghĩa hiệu ứng.

Code trong class BaseViewAnimator như sau:

abstract class BaseViewAnimator {

val DURATION: Long = 1000

private var mAnimatorSet: AnimatorSet? = null private var mDuration = DURATION

private var mRepeatTimes = 0

private var mRepeatMode = ValueAnimator.RESTART

init {

mAnimatorSet = AnimatorSet() }

protected abstract fun prepare(target: View)

open fun setTarget (target: View): BaseViewAnimator? { reset(target)

prepare(target)

return this

}

open fun animate() { start()

}

open fun restart() {

mAnimatorSet = mAnimatorSet!!.clone() start()

}

/**

* reset the view to default status

*

* @param target

*/

open fun reset(target: View?) {

ViewCompat.setAlpha(target, 1f) ViewCompat.setScaleX(target, 1f) ViewCompat.setScaleY(target, 1f) ViewCompat.setTranslationX(target, 0f) ViewCompat.setTranslationY(target, 0f) ViewCompat.setRotation(target, 0f) ViewCompat.setRotationY(target, 0f) ViewCompat.setRotationX(target, 0f) } /** * start to animate */

for (animator in mAnimatorSet!!.childAnimations) {

if (animator is ValueAnimator) {

animator.repeatCount = mRepeatTimes animator.repeatMode = mRepeatMode

} }

mAnimatorSet!!.duration = mDuration mAnimatorSet!!.start()

}

open fun setDuration(duration: Long): BaseViewAnimator? {

mDuration = duration

return this

}

open fun setStartDelay(delay: Long): BaseViewAnimator? { getAnimatorAgent()!!.startDelay = delay

return this

}

open fun getStartDelay(): Long {

return mAnimatorSet!!.startDelay

}

open fun addAnimatorListener(l: Animator.AnimatorListener?): BaseViewAnimator? {

mAnimatorSet !!.addListener(l)

return this

}

open fun cancel() {

mAnimatorSet!!.cancel() }

open fun isRunning(): Boolean {

return mAnimatorSet!!.isRunning

}

open fun isStarted(): Boolean {

return mAnimatorSet!!.isStarted

}

open fun removeAnimatorListener(l: Animator.AnimatorListener) {

mAnimatorSet!!.removeListener(l) }

open fun removeAllListener() {

mAnimatorSet!!.removeAllListeners() }

open fun setInterpolator(interpolator: Interpolator): BaseViewAnimator {

mAnimatorSet !!.interpolator = interpolator

return this

}

open fun getDuration(): Long {

return mDuration

}

open fun getAnimatorAgent (): AnimatorSet {

return mAnimatorSet!! }

open fun setRepeatTimes(repeatTimes: Int): BaseViewAnimator {

mRepeatTimes = repeatTimes

return this

}

open fun setRepeatMode(repeatMode: Int): BaseViewAnimator {

mRepeatMode = repeatMode

return this

} }

Code trong class ZoomInDownAnimator như sau:

class ZoomInDownAnimator: BaseViewAnimator() {

override fun prepare(target: View) { getAnimatorAgent().playTogether(

ObjectAnimator.ofFloat(target, "scaleX", 0.1f, 0.475f,1.0f),

ObjectAnimator.ofFloat(target, "scaleY", 0.1f, 0.475f,1.0f),

ObjectAnimator.ofFloat(target, "translationY", -target.bottom*1.0f, 60*1.0f,0f),

ObjectAnimator.ofFloat(target, "alpha", 0.0f, 1.0f, 1.0f) );

} }

Hình phụ lục 5. Cấu trúc của thư mục common

Code của class ValidationHelpers – có chức năng kiểm tra dữ liệu đầu vào:

const valEMAIL_REGEX = "(?:[a-z0-9!#\$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#\$%&'*+/=?^_`{|}~- ]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-

\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9- ]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0- 9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53- \\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])"

const valMIN_CREDENTIAL_LENGTH = 6

const valMIN_JOKE_LENGTH = 10

fun isEmailValid(email: String) = Pattern.matches(EMAIL_REGEX, email)

fun isPasswordValid(password: String) = password.length >=MIN_CREDENTIAL_LENGTH

fun isUsernameValid(username: String) = username.length >=MIN_CREDENTIAL_LENGTH

fun arePasswordsSame(password: String, repeatPassword: String) =isPasswordValid(password) &&

isPasswordValid(repeatPassword) && password == repeatPassword

fun isValidJoke(jokeText: String) = jokeText.length >= MIN_JOKE_LENGTH

Hình phụ lục 6. Cấu trúc thư mục event

Code của Class PaginationListener:

abstract class PaginationListener (private val layoutManager: LinearLayoutManager):

RecyclerView.OnScrollListener() {

companion object{

const val PAGE_START = 1

const val PAGE_SIZE = 10

}

/**

* Set scrolling threshold here (for now i'm assuming 10 item in one page) */

override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {

super.onScrollStateChanged(recyclerView, newState) }

override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { super.onScrolled(recyclerView, dx, dy)

val visibleItemCount = layoutManager.childCount

val totalItemCount = layoutManager.itemCount

val firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition()

if (!isLoading() && !isLastPage()) {

if (visibleItemCount + firstVisibleItemPosition >= totalItemCount &&

firstVisibleItemPosition >= 0 && totalItemCount >= PAGE_SIZE) {

loadMoreItems() }

} }

protected abstract fun loadMoreItems()

abstract fun isLastPage(): Boolean abstract fun isLoading(): Boolean

}

Hình phụ lục 7. Cấu trúc của thư mục fragment

Code của class BottomSheetInfoBill, class BottomSheetInfoRoom xử lý tương tự:

class BottomSheetInfoBill(val data: Bill): BottomSheetDialogFragment() {

private lateinit var txtRoomName: TextView private lateinit var txtDescription: TextView private lateinit var txtTimeCreate: TextView private lateinit var txtTimePaid: TextView private lateinit var txtTotalBill: TextView private lateinit var txtBillStatus: TextView private lateinit var imgIconBill:ImageView private lateinit var btnPayment:Button private lateinit var btnClose:Button override fun onCreateView(

inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? {

val view:View=inflater.inflate(R.layout.bottom_sheet_info_bill, container, false)

txtRoomName=view.findViewById(R.id.txtRoomName)

txtDescription=view.findViewById(R.id.txtDescription )

txtTimeCreate=view.findViewById(R.id.txtTimeCreate)

txtTimePaid=view.findViewById(R.id.txtTimePaid)

txtTotalBill=view.findViewById(R.id.txtTotalBill)

txtBillStatus=view.findViewById(R.id.txtBillStatus)

imgIconBill=view.findViewById(R.id.imgIconBill)

btnPayment=view.findViewById(R.id.btnPayment)

btnClose=view.findViewById(R.id.btnClose)

return view

}

override fun getTheme(): Int = R.style.BottomSheetDialog

override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState)addControls()

addEvents() }

private fun addControls() {

if (data.id.isNotEmpty()){

val roomOfBill:Room=SplashScreenActivity.listRooms.filter{ p->p.id==data.roomId

}[0]

txtRoomName.text=roomOfBill.roomName if (data.description.isNotEmpty()){

txtDescription.text=data.description

}

txtTimeCreate.text= MyString.convertLongToTime(data.createDateBill,"dd-MM-yyyy HH:mm")

if (data.dateOfPayment!=0L){

txtTimePaid.text= MyString.convertLongToTime(data.createDateBill,"dd-MM-yyyy HH:mm")

}else{

txtBillStatus.text="Unpaid"

txtBillStatus.setTextColor(resources.getColor(R.color.colorRed))

btnPayment.visibility=View.VISIBLE

}

txtTotalBill.text=MyString.convertNumberFormat("%,.0f", data.total).plus("đ" )

val totalBill:ArrayList<DetailBill> = SplashScreenActivity.listDetailBills.filter

{ p->p.billId==data.id} as ArrayList<DetailBill> if

(context!=null){

if (totalBill.size==1){

val service: Service = (SplashScreenActivity.listServices.filter{ p- >p.id==totalBill[0].serviceId})[0]

val uri:String = "@drawable/".plus(service.imageName)// where myresource (without the extension) is the file

var imageResource:Int = requireContext().resources.getIdentifier(uri, null, requireContext().packageName)

val res: Drawable = requireContext().resources.getDrawable(imageResource,

null)

imgIconBill.setImageDrawable(res) }else{

imgIconBill.setImageResource(R.drawable.ic_bill) }

} } }

private fun addEvents() {

btnClose.setOnClickListener {

dialog?.dismiss()

}

btnPayment.setOnClickListener {

if (data.dateOfPayment!=0L||data.id.isEmpty()){

return@setOnClickListener

}

var database:DatabaseReference= Firebase.database.reference val

dateOfPayment:Long= Calendar .getInstance().timeInMillis

data.dateOfPayment=dateOfPayment

val myRef: DatabaseReference = database.child(Configs.TableName_Bill)

myRef.child(data.id).setValue(data).addOnCompleteListener {task->

if (task.isSuccessful){

dialog?.dismiss()

Toast.makeText(it.context,"Payment Successful!!",Toast.LENGTH_LONG ).show()

/* Snackbar.make(it, "Payment Successful!!", Snackbar.LENGTH_LONG) .setAction("Action", null).show()*/

}else{

dialog?.dismiss()

Toast.makeText(it.context,"Payment fail!!",Toast.LENGTH_LONG ).show()

/*Snackbar.make(it, "Payment fail!!", Snackbar.LENGTH_LONG) .setAction("Action", null).show()*/

}

} }

Code của class HomeFragment, class ListBillFragment, ListLodgerFragment, ReportFragment xử lý tương tự:

class HomeFragment : Fragment() {

/ TODO: Rename and change types of parameters private var param1: String? = null private var param2: String? = null

private lateinit var roomSelected: Room

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)

arguments?.let{

param1 = it.getString(ARG_PARAM1)

param2 = it.getString(ARG_PARAM2)

}

}

override fun onCreateView(

inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?

): View? {

/ Inflate the layout for this fragment

return inflater.inflate(R.layout.fragment_home, container, false) }

override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState)

(requireActivity() as AppCompatActivity).supportActionBar?.hide() addControls()

addEvents() }

private fun addEvents() {

btnGenerateQRCode.setOnClickListener {

startActivity(Intent(activity, GenerateQrCodeActivity::class.java))

}

imgEditRoom.setOnClickListener {

val intent:Intent=Intent(activity, RoomActivity::class.java)

intent.putExtra("RoomSelected", InfoRoomActivity.roomSelected) startActivity(intent)

}

btnAddLodger.setOnClickListener {

val intent:Intent=Intent(activity, LodgerActivity::class.java) startActivity(intent)

}

btnConfirmCheckOut.setOnClickListener {

val totalBillUnpaid:Int=(SplashScreenActivity .listBills.filter{ p- >(p.roomId==roomSelected.id&&p.dateOfPayment==0L) }).size

if (totalBillUnpaid>0){

val builder = AlertDialog.Builder(context)

builder.setTitle("Error!")

builder.setMessage("Please payment all bill(unpaid)!")

builder.setPositiveButton("Go to payment",

DialogInterface.OnClickListener { dialog, which ->

dialog.dismiss()

val intent: Intent = Intent(context, BillActivity::class.java)

intent.putExtra("RoomSelected", InfoRoomActivity.roomSelected) startActivity(intent)

})

builder.setNegativeButton("No",

DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() })

builder.create().show()

return@setOnClickListener

}

InfoRoomActivity.roomSelected.isFull=false val myRef2: DatabaseReference =

Firebase.database.reference.child(Configs.TableName_Room)

myRef2.child(InfoRoomActivity.roomSelected.id).setValue(InfoRoomActivity.roomSelected).addOnCo mpleteListener { task ->

if (task.isSuccessful) {

Toast.makeText(activity, "Room status is empty", Toast.LENGTH_LONG).show() }

}

val listLodger:ArrayList<Lodger> = SplashScreenActivity.listLodgers.filter{ p- >p.roomId==InfoRoomActivity.roomSelected.id} as ArrayList<Lodger>

for (lodger:Lodger in listLodger){

val myRef3: DatabaseReference =

Firebase.database.reference.child(Configs.TableName_Lodger)

lodger.roomId=""

myRef3.child(lodger.id).setValue(lodger) }

val ft: FragmentTransaction = requireFragmentManager().beginTransaction()

ft.detach(this).attach(this).commit()

}

}

private fun addControls() {

roomSelected = if (InfoRoomActivity.roomSelected!=null){

InfoRoomActivity.roomSelected

}else{ Room() }

txtRoomName.text=roomSelected.roomName

txtRoomRate.text=

MyString.Companion.convertNumberFormat("%,d",

roomSelected.roomRate).plus( " đ"

)

startCountAnimation(txtElectricityIndex, 0, roomSelected.electricityIndex) startCountAnimation(txtWaterIndex, 0, roomSelected.waterIndex)

/*txtElectricityIndex.text=roomSelected.electricityIndex.toString() txtWaterIndex.text=roomSelected.waterIndex.toString()*/

if (!roomSelected.isFull){

txtRoomStatus.text= "Empty"

/ imgIconRoom.setImageResource(R.drawable.ic_room_empty)

btnConfirmCheckOut.visibility=View.GONE

btnAddLodger.visibility=View.VISIBLE

}

val totalLodger:Int=(SplashScreenActivity.listLodgers.filter{ p- >p.roomId==roomSelected.id}).size

startCountAnimation(txtTotalLodger, 0, totalLodger)

val totalBill:Int=(SplashScreenActivity.listBills.filter{ p- >p.roomId==roomSelected.id}).size

startCountAnimation(txtTotalBill, 0, totalBill) txtRoomId.text=roomSelected.id

val totalBillUnpaid:Int=(SplashScreenActivity.listBills.filter{ p- >(p.roomId==roomSelected.id&&p.dateOfPayment==0L) }).size

startCountAnimation(txtTotalBillUnPaid, 0, totalBillUnpaid) }

private fun startCountAnimation( view: TextView,

numberStart: Int = 0, numberEnd: Int = 600, duration: Long = 1000L

) {

val animator = ValueAnimator.ofInt(numberStart, numberEnd)//0 is min number, 600 is max number

animator.duration = duration //Duration is in milliseconds animator.addUpdateListener { animation -> view.text =

animation.animatedValue.toString() }

animator.start() }

companion object {

/**

/ TODO: Rename and change types and number of parameters @JvmStatic

fun newInstance(param1: String, param2: String) = HomeFragment().apply{

arguments = Bundle().apply

{ putString(ARG_PARAM1, param1) putString(ARG_PARAM2, param2) } } } }

Bảng phụ lục 2. Bảng mô tả cấu trúc thư mục con của hình phụ lục 8 STT Tên Class 1 Bill 2 DetailBill 3 DetailRoom 4 Lodger 5 Room 6 Service

Code của class Bill, các class DetailBill, DetailRoom, Lodger, Room, Service xử lý tương

tự:

class Bill:Serializable {

private var _id:String=""

private var _billName:String=""

private var _createDateBill:Long = 0

private var _dateOfPayment:Long =0

private var _total:Double=0.0

private var _roomId:String=""

var _isSection:Boolean=false private var _description:String=""

constructor(){}

constructor(_id: String,_billName:String, _createDateBill: Long, _dateOfPayment: Long, _roomId: String,_isSection:Boolean=false,_total:Double, _description:String="") {

this._id = _id

this._billName = _billName

this._createDateBill = _createDateBill

this._dateOfPayment = _dateOfPayment

this._roomId = _roomId

this._isSection=_isSection

this._total=_total

this._description=_description } var id:String get() { return _id } set(value) {

this._id=value }

var billName:String get() {

return _billName

}

set(value) {

this._billName=value }

var description:String get() {

return _description

}

set(value) {

this._description=value }

var createDateBill: Long get() {

return _createDateBill

}

set(value) {

this._createDateBill=value }

var total: Double get() {

return _total

}

set(value) {

this._total=value }

var dateOfPayment: Long get() {

return _dateOfPayment

}

set(value) {

this._dateOfPayment=value }

var roomId: String get() {

return _roomId

}

set(value) {

}

override fun toString(): String {

return this._billName

}

fun copy(bill:Bill, _isSection:Boolean=false):Bill{

return

Bill(bill.id,bill.billName,bill.createDateBill,bill.dateOfPayment,bill.roomId,_isSection,bill. total

,bill.description) }

}

Bảng phụ lục 3. Bảng mô tả cấu trúc thư mục con của hình phụ lục 9 STT Tên Class 1 AddBillActivity 2 AddDetailBill 3 AddServiceActivity 4 BillActivity 5 DashBoardActivity 6 DetailBillActivity 7 DetailLodgerActivity 8 GenerateQrCodeActivity 9 InfoRoomActivity 10 LodgerActivity 11 LoginActivity 12 MainActivity 13 ProfileActivity 14 RegisterActivity 15 ReportActivity 16 ResetPasswordActivity 17 RoomActivity 18 ServiceActivity 19 SplashScreenActivity 20 WriteIndexActivity

Phụ lục B. Cấu trúc ứng dụng Search Motel Information

Hình phụ lục 10. Cấu trúc chung của ứng dụng Search Motel Information

Hình phụ lục 11. Cấu trúc thư mục com.thanhtrung Bảng phụ lục 4. Bảng mô tả cấu trúc thư mục con của hình phụ lục 11

1 adapters 2 common 3 event 4 fragment 5 models 6 motelroomttlodger 7 os 8 others 9 view

Hình phụ lục 12. Cấu trúc của thư mục adapters

Hình phụ lục 14. Cấu trúc của thư mục models

Hình phụ lục 15. Cấu trúc thư mục motelroomttlodger

Một phần của tài liệu đồ án tốt nghiệp ứng dụng quản lý phòng trọ (Trang 135 - 159)