From f1d2895202fe65f63006fe4fdc8e2c28c518ef84 Mon Sep 17 00:00:00 2001 From: Aryankc2 Date: Wed, 30 Apr 2025 10:22:07 +0530 Subject: [PATCH] changes --- .../com/example/fieldagent/FirstFragment.kt | 44 ------ .../com/example/fieldagent/MainActivity.kt | 59 -------- .../com/example/fieldagent/SecondFragment.kt | 44 ------ .../ui/damagedetails/DamageDetailsFragment.kt | 7 +- .../ui/damagelist/DamageListFragment.kt | 140 ++++++++++++++++++ app/src/main/res/values/strings.xml | 10 +- 6 files changed, 153 insertions(+), 151 deletions(-) delete mode 100644 app/src/main/java/com/example/fieldagent/FirstFragment.kt delete mode 100644 app/src/main/java/com/example/fieldagent/MainActivity.kt delete mode 100644 app/src/main/java/com/example/fieldagent/SecondFragment.kt 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