changes
This commit is contained in:
parent
baf0c5cbca
commit
f1d2895202
|
@ -1,44 +0,0 @@
|
||||||
package com.example.fieldagent
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import com.example.fieldagent.databinding.FragmentFirstBinding
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple [Fragment] subclass as the default destination in the navigation.
|
|
||||||
*/
|
|
||||||
class FirstFragment : Fragment() {
|
|
||||||
|
|
||||||
private var _binding: FragmentFirstBinding? = null
|
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View {
|
|
||||||
|
|
||||||
_binding = FragmentFirstBinding.inflate(inflater, container, false)
|
|
||||||
return binding.root
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
binding.buttonFirst.setOnClickListener {
|
|
||||||
// findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
|
||||||
super.onDestroyView()
|
|
||||||
_binding = null
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
package com.example.fieldagent
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.navigation.findNavController
|
|
||||||
import androidx.navigation.ui.AppBarConfiguration
|
|
||||||
import androidx.navigation.ui.navigateUp
|
|
||||||
import androidx.navigation.ui.setupActionBarWithNavController
|
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuItem
|
|
||||||
import com.example.fieldagent.databinding.ActivityMainBinding
|
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
|
||||||
|
|
||||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
|
||||||
private lateinit var binding: ActivityMainBinding
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
binding = ActivityMainBinding.inflate(layoutInflater)
|
|
||||||
setContentView(binding.root)
|
|
||||||
|
|
||||||
setSupportActionBar(binding.toolbar)
|
|
||||||
|
|
||||||
val navController = findNavController(R.id.nav_host_fragment_content_main)
|
|
||||||
appBarConfiguration = AppBarConfiguration(navController.graph)
|
|
||||||
setupActionBarWithNavController(navController, appBarConfiguration)
|
|
||||||
|
|
||||||
binding.fab.setOnClickListener { view ->
|
|
||||||
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
|
||||||
.setAction("Action", null)
|
|
||||||
.setAnchorView(R.id.fab).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
|
||||||
// Inflate the menu; this adds items to the action bar if it is present.
|
|
||||||
menuInflater.inflate(R.menu.menu_main, menu)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
|
||||||
// Handle action bar item clicks here. The action bar will
|
|
||||||
// automatically handle clicks on the Home/Up button, so long
|
|
||||||
// as you specify a parent activity in AndroidManifest.xml.
|
|
||||||
return when (item.itemId) {
|
|
||||||
R.id.action_settings -> true
|
|
||||||
else -> super.onOptionsItemSelected(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSupportNavigateUp(): Boolean {
|
|
||||||
val navController = findNavController(R.id.nav_host_fragment_content_main)
|
|
||||||
return navController.navigateUp(appBarConfiguration)
|
|
||||||
|| super.onSupportNavigateUp()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
package com.example.fieldagent
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.fragment.app.Fragment
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.navigation.fragment.findNavController
|
|
||||||
import com.example.fieldagent.databinding.FragmentSecondBinding
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple [Fragment] subclass as the second destination in the navigation.
|
|
||||||
*/
|
|
||||||
class SecondFragment : Fragment() {
|
|
||||||
|
|
||||||
private var _binding: FragmentSecondBinding? = null
|
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View {
|
|
||||||
|
|
||||||
_binding = FragmentSecondBinding.inflate(inflater, container, false)
|
|
||||||
return binding.root
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
binding.buttonSecond.setOnClickListener {
|
|
||||||
// findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
|
||||||
super.onDestroyView()
|
|
||||||
_binding = null
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -306,8 +306,11 @@ class DamageDetailsFragment : Fragment() {
|
||||||
|
|
||||||
if (from=="edit")
|
if (from=="edit")
|
||||||
{
|
{
|
||||||
val jsonArray = JSONArray(urlList)
|
for ((index, url) in urlList.withIndex()) {
|
||||||
hashMap["images"] = jsonArray.toString().toRequestBody("application/json".toMediaType())
|
val key = "images[$index]"
|
||||||
|
val body = url.toRequestBody("text/plain".toMediaType()) // or "application/json" if backend expects
|
||||||
|
hashMap[key] = body
|
||||||
|
}
|
||||||
viewModel.editDamage(damageId,hashMap,imageParts)
|
viewModel.editDamage(damageId,hashMap,imageParts)
|
||||||
}else{
|
}else{
|
||||||
viewModel.addDamage(hashMap,imageParts)
|
viewModel.addDamage(hashMap,imageParts)
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
package com.example.fieldagent.ui.damagelist
|
package com.example.fieldagent.ui.damagelist
|
||||||
|
|
||||||
|
import android.content.ContentValues
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.pdf.PdfDocument
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Environment
|
||||||
|
import android.provider.MediaStore
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
@ -21,7 +29,12 @@ import com.example.fieldagent.utils.showConfirmDialog
|
||||||
import com.example.fieldagent.utils.visible
|
import com.example.fieldagent.utils.visible
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import java.io.File
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
|
@ -172,8 +185,135 @@ class DamageListFragment : Fragment() {
|
||||||
findNavController().popBackStack()
|
findNavController().popBackStack()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.btnExportPdf.setOnClickListener {
|
||||||
|
setUpPdf()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setUpPdf(){
|
||||||
|
val pdfDocument = PdfDocument()
|
||||||
|
val pageInfo = PdfDocument.PageInfo.Builder(595, 842, 1).create()
|
||||||
|
val page = pdfDocument.startPage(pageInfo)
|
||||||
|
val canvas = page.canvas
|
||||||
|
|
||||||
|
val borderPaint = Paint().apply {
|
||||||
|
color = Color.BLACK
|
||||||
|
style = Paint.Style.STROKE
|
||||||
|
strokeWidth = 1f
|
||||||
|
}
|
||||||
|
|
||||||
|
val textPaint = Paint().apply {
|
||||||
|
textSize = 12f
|
||||||
|
color = Color.BLACK
|
||||||
|
style = Paint.Style.FILL
|
||||||
|
isAntiAlias = true
|
||||||
|
}
|
||||||
|
|
||||||
|
val whiteTextPaint = Paint(textPaint).apply { color = Color.WHITE }
|
||||||
|
|
||||||
|
val fillPaint = Paint().apply {
|
||||||
|
style = Paint.Style.FILL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Column layout
|
||||||
|
val colWidths = listOf(40f, 100f, 60f, 100f, 60f, 120f)
|
||||||
|
val rowHeight = 40f
|
||||||
|
val startX = 40f
|
||||||
|
var startY = 60f
|
||||||
|
|
||||||
|
val title = "Damage Report Table"
|
||||||
|
val headers = listOf("No.", "Item", "Number", "Individual Cost", "Unit", "Total Cost (Riyals)")
|
||||||
|
val rows = listOf(
|
||||||
|
listOf("1", "Chair", "4", "50", "pcs", "200"),
|
||||||
|
listOf("2", "Table", "2", "150", "pcs", "300"),
|
||||||
|
listOf("3", "مكتب", "1", "500", "قطعة", "500"),
|
||||||
|
listOf("4", "Desk", "1", "450", "pcs", "450")
|
||||||
|
)
|
||||||
|
|
||||||
|
val centerAlignedColumns = setOf(0, 2, 3, 5) // columns to center text
|
||||||
|
|
||||||
|
fun drawCellText(canvas: Canvas, text: String, x: Float, y: Float, width: Float, paint: Paint, center: Boolean) {
|
||||||
|
val drawX = if (center) {
|
||||||
|
x + (width / 2f) - (paint.measureText(text) / 2f)
|
||||||
|
} else {
|
||||||
|
x + 5f
|
||||||
|
}
|
||||||
|
canvas.drawText(text, drawX, y, paint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Draw title row ---
|
||||||
|
fillPaint.color = Color.parseColor("#006400") // dark green
|
||||||
|
canvas.drawRect(startX, startY, startX + colWidths.sum(), startY + rowHeight, fillPaint)
|
||||||
|
canvas.drawRect(startX, startY, startX + colWidths.sum(), startY + rowHeight, borderPaint)
|
||||||
|
|
||||||
|
val titleX = startX + (colWidths.sum() / 2f) - (whiteTextPaint.measureText(title) / 2f)
|
||||||
|
canvas.drawText(title, titleX, startY + 25f, whiteTextPaint)
|
||||||
|
startY += rowHeight
|
||||||
|
|
||||||
|
// --- Draw header row ---
|
||||||
|
fillPaint.color = Color.parseColor("#90EE90") // light green
|
||||||
|
var x = startX
|
||||||
|
for ((i, header) in headers.withIndex()) {
|
||||||
|
val width = colWidths[i]
|
||||||
|
canvas.drawRect(x, startY, x + width, startY + rowHeight, fillPaint)
|
||||||
|
canvas.drawRect(x, startY, x + width, startY + rowHeight, borderPaint)
|
||||||
|
drawCellText(canvas, header, x, startY + 25f, width, textPaint, i in centerAlignedColumns)
|
||||||
|
x += width
|
||||||
|
}
|
||||||
|
startY += rowHeight
|
||||||
|
|
||||||
|
// --- Draw data rows ---
|
||||||
|
for ((index, row) in rows.withIndex()) {
|
||||||
|
fillPaint.color = if (index % 2 == 0) Color.WHITE else Color.parseColor("#E6FFE6")
|
||||||
|
x = startX
|
||||||
|
for ((i, cell) in row.withIndex()) {
|
||||||
|
val width = colWidths[i]
|
||||||
|
canvas.drawRect(x, startY, x + width, startY + rowHeight, fillPaint)
|
||||||
|
canvas.drawRect(x, startY, x + width, startY + rowHeight, borderPaint)
|
||||||
|
drawCellText(canvas, cell, x, startY + 25f, width, textPaint, i in centerAlignedColumns)
|
||||||
|
x += width
|
||||||
|
}
|
||||||
|
startY += rowHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
pdfDocument.finishPage(page)
|
||||||
|
|
||||||
|
|
||||||
|
val fileName = "damage_report_" + SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(
|
||||||
|
Date()
|
||||||
|
)
|
||||||
|
savePdfToDocuments(pdfDocument, fileName)
|
||||||
|
|
||||||
|
}
|
||||||
|
fun savePdfToDocuments( pdfDocument: PdfDocument, fileName: String) {
|
||||||
|
val contentValues = ContentValues().apply {
|
||||||
|
put(MediaStore.MediaColumns.DISPLAY_NAME, "$fileName.pdf")
|
||||||
|
put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf")
|
||||||
|
put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS)
|
||||||
|
put(MediaStore.MediaColumns.IS_PENDING, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
val resolver = requireActivity().contentResolver
|
||||||
|
val uri = resolver.insert(MediaStore.Files.getContentUri("external"), contentValues)
|
||||||
|
|
||||||
|
uri?.let {
|
||||||
|
resolver.openOutputStream(it)?.use { outputStream ->
|
||||||
|
pdfDocument.writeTo(outputStream)
|
||||||
|
pdfDocument.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
contentValues.clear()
|
||||||
|
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0)
|
||||||
|
resolver.update(uri, contentValues, null, null)
|
||||||
|
|
||||||
|
Toast.makeText(context, "PDF saved to Documents!", Toast.LENGTH_LONG).show()
|
||||||
|
} ?: run {
|
||||||
|
Toast.makeText(context, "Failed to save PDF", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun clickItem(pos: Int) {
|
fun clickItem(pos: Int) {
|
||||||
val gson = Gson()
|
val gson = Gson()
|
||||||
|
|
|
@ -158,6 +158,14 @@
|
||||||
<string name="save">Save</string>
|
<string name="save">Save</string>
|
||||||
<string name="profile_updated_successfully">Profile updated successfully</string>
|
<string name="profile_updated_successfully">Profile updated successfully</string>
|
||||||
<string name="are_you_sure_you_want_to_delete">Are you sure you want to delete?</string>
|
<string name="are_you_sure_you_want_to_delete">Are you sure you want to delete?</string>
|
||||||
|
<string name="damage_report_table">Damage Report Table</string>
|
||||||
|
<string name="no.">No.</string>
|
||||||
|
<string name="item">Item</string>
|
||||||
|
<string name="number">Number</string>
|
||||||
|
<string name="unit">Unit</string>
|
||||||
|
<string name="total_cost_in_riyals">Total Cost in Riyals</string>
|
||||||
|
<string name="total_cost">Total Cost</string>
|
||||||
|
<string name="individual_cost">Individual Cost in Riyals</string>
|
||||||
|
|
||||||
|
|
||||||
<string-array name="availability">
|
<string-array name="availability">
|
||||||
|
@ -205,6 +213,4 @@
|
||||||
<item>@string/liter</item>
|
<item>@string/liter</item>
|
||||||
<item>@string/kg</item>
|
<item>@string/kg</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<!-- TODO: Remove or change this placeholder text -->
|
|
||||||
<string name="hello_blank_fragment">Hello blank fragment</string>
|
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue