diff --git a/app/src/main/java/com/example/fieldagent/FirstFragment.kt b/app/src/main/java/com/example/fieldagent/FirstFragment.kt
deleted file mode 100644
index 69c3e2d..0000000
--- a/app/src/main/java/com/example/fieldagent/FirstFragment.kt
+++ /dev/null
@@ -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
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/fieldagent/MainActivity.kt b/app/src/main/java/com/example/fieldagent/MainActivity.kt
deleted file mode 100644
index 17e7555..0000000
--- a/app/src/main/java/com/example/fieldagent/MainActivity.kt
+++ /dev/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()
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/fieldagent/SecondFragment.kt b/app/src/main/java/com/example/fieldagent/SecondFragment.kt
deleted file mode 100644
index 0555f7b..0000000
--- a/app/src/main/java/com/example/fieldagent/SecondFragment.kt
+++ /dev/null
@@ -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
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/fieldagent/ui/damagedetails/DamageDetailsFragment.kt b/app/src/main/java/com/example/fieldagent/ui/damagedetails/DamageDetailsFragment.kt
index 70bac60..376d84b 100644
--- a/app/src/main/java/com/example/fieldagent/ui/damagedetails/DamageDetailsFragment.kt
+++ b/app/src/main/java/com/example/fieldagent/ui/damagedetails/DamageDetailsFragment.kt
@@ -306,8 +306,11 @@ class DamageDetailsFragment : Fragment() {
if (from=="edit")
{
- val jsonArray = JSONArray(urlList)
- hashMap["images"] = jsonArray.toString().toRequestBody("application/json".toMediaType())
+ for ((index, url) in urlList.withIndex()) {
+ 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)
}else{
viewModel.addDamage(hashMap,imageParts)
diff --git a/app/src/main/java/com/example/fieldagent/ui/damagelist/DamageListFragment.kt b/app/src/main/java/com/example/fieldagent/ui/damagelist/DamageListFragment.kt
index 6709f6a..298c716 100644
--- a/app/src/main/java/com/example/fieldagent/ui/damagelist/DamageListFragment.kt
+++ b/app/src/main/java/com/example/fieldagent/ui/damagelist/DamageListFragment.kt
@@ -1,10 +1,18 @@
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.Environment
+import android.provider.MediaStore
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.Toast
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
@@ -21,7 +29,12 @@ import com.example.fieldagent.utils.showConfirmDialog
import com.example.fieldagent.utils.visible
import com.google.gson.Gson
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.Locale
import javax.inject.Inject
@@ -172,8 +185,135 @@ class DamageListFragment : Fragment() {
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) {
val gson = Gson()
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8a4a474..1a8fce9 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -158,6 +158,14 @@
Save
Profile updated successfully
Are you sure you want to delete?
+ Damage Report Table
+ No.
+ Item
+ Number
+ Unit
+ Total Cost in Riyals
+ Total Cost
+ Individual Cost in Riyals
@@ -205,6 +213,4 @@
- @string/liter
- @string/kg
-
- Hello blank fragment
\ No newline at end of file