diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
index 329860c..8b909e6 100644
--- a/.idea/deploymentTargetSelector.xml
+++ b/.idea/deploymentTargetSelector.xml
@@ -13,6 +13,9 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/dreamteam/timelapse/CustomSwipeRefreshLayout.kt b/app/src/main/java/com/dreamteam/timelapse/CustomSwipeRefreshLayout.kt
index 6842144..4527b10 100644
--- a/app/src/main/java/com/dreamteam/timelapse/CustomSwipeRefreshLayout.kt
+++ b/app/src/main/java/com/dreamteam/timelapse/CustomSwipeRefreshLayout.kt
@@ -1,5 +1,6 @@
package com.dreamteam.timelapse
+import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
import android.util.Log
@@ -7,6 +8,8 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
class CustomSwipeRefreshLayout(context: Context, attrs: AttributeSet) : SwipeRefreshLayout(context, attrs) {
init {
+ this.setEnabled(true)
+ this.setRefreshing(true)
Log.d("CustomSwipeRefreshLayout", "CustomSwipeRefreshLayout instancié")
}
override fun canChildScrollUp(): Boolean {
@@ -15,4 +18,22 @@ class CustomSwipeRefreshLayout(context: Context, attrs: AttributeSet) : SwipeRef
//Log.i("CustomSwipeRefreshLayout", "canChildScrollUp: ${view?.canScrollVertically(-1)}")
return view != null && view.canScrollVertically(-1)
}
+ private var mMeasured = false
+ private var mPreMeasureRefreshing = false
+
+
+// fun dragDown(){
+// this.post {
+// Log.i("SwipeRefreshLayout", "Je suis delanché par le code")
+// val distanceToMove = 200 // La distance que l'on veut faire descendre l'élément, ajustable
+// val valueAnimator = ValueAnimator.ofInt(0, distanceToMove)
+// valueAnimator.addUpdateListener { animation ->
+// val value = animation.animatedValue as Int
+// // Manipule le mouvement de l'animation du rafraîchissement
+// this.setProgressViewOffset(false, 0, value)
+// }
+// valueAnimator.duration = 500 // Durée de l'animation
+// valueAnimator.start()
+// }
+// }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/dreamteam/timelapse/ImageAdapter.kt b/app/src/main/java/com/dreamteam/timelapse/ImageAdapter.kt
new file mode 100644
index 0000000..bcf452a
--- /dev/null
+++ b/app/src/main/java/com/dreamteam/timelapse/ImageAdapter.kt
@@ -0,0 +1,62 @@
+package com.dreamteam.timelapse
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.Toast
+import androidx.recyclerview.widget.RecyclerView
+import com.bumptech.glide.Glide
+import com.bumptech.glide.request.target.SimpleTarget
+import java.io.File
+import java.io.FileOutputStream
+import java.io.IOException
+import com.bumptech.glide.request.transition.Transition
+
+
+
+class ImageAdapter(private val imageUrls: List) : RecyclerView.Adapter() {
+
+ // ViewHolder qui contient l'ImageView
+ class ImageViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
+ val imageView: ImageView = itemView.findViewById(R.id.imageView)
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder {
+ val view = LayoutInflater.from(parent.context).inflate(R.layout.item_image, parent, false)
+ return ImageViewHolder(view)
+ }
+
+ override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
+ val imageUrl = imageUrls[position]
+ //Log.e("ImageAdapter", imageUrl)
+ Glide.with(holder.itemView.context)
+ .load(imageUrl) // Charge l'image via Glide
+ .into(holder.imageView) // Affiche l'image dans l'ImageView
+ }
+ private fun downloadImage(url: String, context: Context) {
+ Glide.with(context)
+ .asBitmap()
+ .load(url)
+ .into(object : SimpleTarget() {
+ override fun onResourceReady(resource: Bitmap, transition: Transition?) {
+ // Save the image to the app's internal storage
+ val file = File(context.filesDir, "downloaded_image.jpg")
+ try {
+ val fileOutputStream = FileOutputStream(file)
+ resource.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream)
+ fileOutputStream.flush()
+ fileOutputStream.close()
+ Toast.makeText(context, "Image downloaded successfully", Toast.LENGTH_SHORT).show()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ Toast.makeText(context, "Error downloading image", Toast.LENGTH_SHORT).show()
+ }
+ }
+ })
+ }
+ override fun getItemCount(): Int = imageUrls.size
+}
diff --git a/app/src/main/java/com/dreamteam/timelapse/MainActivity.kt b/app/src/main/java/com/dreamteam/timelapse/MainActivity.kt
index 7895cfb..9c4c350 100644
--- a/app/src/main/java/com/dreamteam/timelapse/MainActivity.kt
+++ b/app/src/main/java/com/dreamteam/timelapse/MainActivity.kt
@@ -1,36 +1,46 @@
package com.dreamteam.timelapse
-import android.R
-import com.dreamteam.timelapse.R as Rtmp
+import android.content.DialogInterface
import android.os.Bundle
import android.util.Log
+import android.view.LayoutInflater
import android.view.View
+import android.widget.EditText
+import android.widget.LinearLayout
+import androidx.appcompat.app.AlertDialog
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 androidx.viewpager2.widget.ViewPager2
import com.dreamteam.timelapse.databinding.ActivityMainBinding
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
+import com.dreamteam.timelapse.R as Rtmp
+import com.dreamteam.timelapse.R
+import com.dreamteam.timelapse.data.ApiService
+import com.dreamteam.timelapse.data.ProjectRepository
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
class MainActivity : AppCompatActivity() {
private lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var binding: ActivityMainBinding
+ private lateinit var dialog: AlertDialog
+ private lateinit var projectRepository : ProjectRepository
override fun onCreate(savedInstanceState: Bundle?) {
// super.onCreate(savedInstanceState)
//
-
+ val retrofit = Retrofit.Builder()
+ .baseUrl("https://timelapse.kerboul.me/api/")
+ .addConverterFactory(GsonConverterFactory.create())
+ .build()
+ projectRepository = ProjectRepository(retrofit.create(ApiService::class.java))
Log.d("mainActivity", "La main activity est créée")
-// setSupportActionBar(binding.toolbar)
-//
super.onCreate(savedInstanceState)
//val navController = findNavController(R.id.nav_host_fragment_content_main)
//appBarConfiguration = AppBarConfiguration(navController.graph)
@@ -46,13 +56,13 @@ class MainActivity : AppCompatActivity() {
setContentView(Rtmp.layout.activity_main)
val tabLayout = findViewById(Rtmp.id.tabLayout) as TabLayout
val viewPager = findViewById(Rtmp.id.viewPager) as ViewPager2
+ createDialog(findViewById(Rtmp.id.fab))
// Configurer l'adapter pour ViewPager2
var tabsAdapter = TabsAdapter(this)
viewPager.setAdapter(tabsAdapter)
-
// Connecter le ViewPager au TabLayout
TabLayoutMediator(
tabLayout, viewPager
@@ -63,12 +73,39 @@ class MainActivity : AppCompatActivity() {
}
}.attach()
- // Bouton flottant
-// binding.fab.setOnClickListener { view ->
-// Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
-// //.setAction("Action", null) //sert à rien
-// .setAnchorView(R.id.fab).show() //au dessus du bouton mail
-// }
+ //Bouton flottant
+ findViewById(Rtmp.id.fab).setOnClickListener { view -> run {
+ this.dialog.show()
+ }
+ }
+ }
+
+ fun createDialog(viewfortoast: View){
+ //Preparing views
+ val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
+ val layout: View = inflater.inflate(
+ R.layout.project_create_dialog_layout,
+ findViewById(R.id.layout_root)
+ )
+
+ val project_name = layout.findViewById(Rtmp.id.project_name_dialog) as EditText
+ val project_desc = layout.findViewById(Rtmp.id.project_desc_dialog) as EditText
+
+ val builder: AlertDialog.Builder = AlertDialog.Builder(this)
+ builder.setView(layout)
+ builder.setPositiveButton("Save",
+ DialogInterface.OnClickListener { dialog, which ->
+ val onSuccess : () -> Unit = {dialog.dismiss() ; Snackbar.make(viewfortoast, "Nouveau projet créé", Snackbar.LENGTH_LONG).setAnchorView(Rtmp.id.fab).show() ; }
+ val onError : (s:String) -> Unit = { s-> Snackbar.make(viewfortoast, "Erreur lors de la création du projet. ${s}", Snackbar.LENGTH_LONG).setAnchorView(Rtmp.id.fab).show() }
+
+ projectRepository.createProject(project_name.text.toString(), project_desc.text.toString(), onSuccess, onError)
+
+ })
+ builder.setNegativeButton("Cancel",
+ DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() })
+ val dialog: AlertDialog = builder.create()
+ this.dialog = dialog
+
}
// override fun onSupportNavigateUp(): Boolean {
diff --git a/app/src/main/java/com/dreamteam/timelapse/ProjectActivity.kt b/app/src/main/java/com/dreamteam/timelapse/ProjectActivity.kt
index 687e7c3..0b69640 100644
--- a/app/src/main/java/com/dreamteam/timelapse/ProjectActivity.kt
+++ b/app/src/main/java/com/dreamteam/timelapse/ProjectActivity.kt
@@ -1,61 +1,74 @@
package com.dreamteam.timelapse
import android.graphics.Color
+import android.graphics.Rect
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
-import androidx.navigation.ui.AppBarConfiguration
-import androidx.viewpager2.widget.ViewPager2
+import androidx.recyclerview.widget.RecyclerView
+import androidx.recyclerview.widget.StaggeredGridLayoutManager
+import com.dreamteam.timelapse.data.ApiService
+import com.dreamteam.timelapse.data.Measurement
+import com.dreamteam.timelapse.data.Project
+import com.dreamteam.timelapse.data.ProjectRepository
import com.dreamteam.timelapse.databinding.ProjectBinding
-import com.google.android.material.tabs.TabLayout
-import com.dreamteam.timelapse.R
-import com.github.mikephil.charting.charts.LineChart
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.data.LineData
import com.github.mikephil.charting.data.LineDataSet
+import com.github.mikephil.charting.formatter.ValueFormatter
+import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+import java.text.SimpleDateFormat
+import java.util.Date
+import java.util.Locale
+
class ProjectActivity : AppCompatActivity() {
private lateinit var binding: ProjectBinding
+ private lateinit var projectRepository: ProjectRepository
+ private lateinit var apiService: ApiService // Déclare l'apiService
+ private var measures: List = emptyList() // Déclare une liste de projets vide
+ private var project: Project? = null
+ private var imageUrls = emptyList()
+ private class GridSpacingItemDecoration(private val spacing: Int) : RecyclerView.ItemDecoration() {
+ override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
+ val position = parent.getChildAdapterPosition(view) // Position de l'item
+ if (position == RecyclerView.NO_POSITION) return
+
+ outRect.left = spacing / 2
+ outRect.right = spacing / 2
+ outRect.top = spacing
+ }
+ }
override fun onCreate(savedInstanceState: Bundle?) {
- val project = intent.getParcelableExtra("PROJECT") // -1 est la valeur par défaut si l'ID n'est pas trouvé
- Log.d("project", "La project activity "+project?.id+" est créée")
+ val retrofit = Retrofit.Builder()
+ .baseUrl("https://timelapse.kerboul.me/api/")
+ .addConverterFactory(GsonConverterFactory.create())
+ .build()
+ apiService = retrofit.create(ApiService::class.java) // Crée une instance d'ApiService
+ projectRepository = ProjectRepository(apiService) // Tu initialises ton repository
+
+ this.project = intent.getParcelableExtra("PROJECT") // -1 est la valeur par défaut si l'ID n'est pas trouvé
+ Log.d("project", "La project activity "+this.project?.id+" est créée")
super.onCreate(savedInstanceState)
- binding = ProjectBinding.inflate(layoutInflater)
+ this.binding = ProjectBinding.inflate(layoutInflater)
setContentView(binding.root)
- // Initialisation du graphique
- val temperatureHumidityChart = binding.temperatureHumidityChart
- // Données fictives (température et humidité)
- val temperatureEntries = mutableListOf()
- val humidityEntries = mutableListOf()
+ initProjectInfo()
- // Ajouter des points de données (exemples)
- temperatureEntries.add(Entry(0f, 25f)) // (temps, température)
- humidityEntries.add(Entry(0f, 60f)) // (temps, humidité)
+ fetchMeasuresAndRebuildGraph()
+ val swipeRefreshLayout = binding.swipeRefreshLayout
+ swipeRefreshLayout.setOnRefreshListener {
+ fetchMeasuresAndRebuildGraph()
+ Log.d("ProjetsFrag", "Actualisation des projets")
+ }
- // Créer des LineDataSet pour chaque série de données
- val temperatureDataSet = LineDataSet(temperatureEntries, "Température")
- val humidityDataSet = LineDataSet(humidityEntries, "Hygrométrie")
- // Ajouter les datasets au graphique
- val lineData = LineData(temperatureDataSet, humidityDataSet)
- temperatureHumidityChart.data = lineData
-
- // Personnaliser le graphique (par exemple, couleur, légende, etc.)
- temperatureDataSet.color = Color.RED
- humidityDataSet.color = Color.BLUE
-
- temperatureHumidityChart.invalidate() // Rafraîchir le graphique
-
- //super.onCreate(savedInstanceState)
- val nameview = findViewById(R.id.project_name)
- val descriptionview = findViewById(R.id.project_name)
- val beginview = findViewById(R.id.project_start_date)
- val statusview = findViewById(R.id.project_status)
@@ -66,4 +79,92 @@ class ProjectActivity : AppCompatActivity() {
// .setAnchorView(R.id.fab).show() //au dessus du bouton mail
// }
}
+
+
+ fun fetchMeasuresAndRebuildGraph(){
+ this.project?.let{
+ projectRepository.fetchMeasurementsOfProject(it.id,
+ onSuccess = { measures ->
+ Log.d("ProjectActivity", "Mesures reçus : $measures")
+ this.measures = measures
+ if(this.measures.size > 0)
+ initGraph(this.measures)
+
+ val adapter = ImageAdapter(this.measures.map { m-> "https://timelapse.kerboul.me/api/images/${m.project_id}/${m.order_id}"}) //ImageAdapter(imageUrls)
+ binding.imagesList.layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.HORIZONTAL)
+ binding.imagesList.addItemDecoration(GridSpacingItemDecoration(16)) // 16px spacing
+ binding.imagesList.adapter = adapter
+
+ binding.swipeRefreshLayout.isRefreshing = false
+ //this.projectAdapter = ProjectAdapter(this.projects, this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir)
+ //this.recyclerView.adapter = this.projectAdapter
+ // Mettre à jour le RecyclerView ou autre traitement
+ },
+ onError = { errorMessage ->
+ Log.e("ProjectActivity", errorMessage)
+ fetchMeasuresAndRebuildGraph()
+ })
+ }
+ }
+
+ fun initGraph(lm : List){
+ val temperatureHumidityChart = this.binding.temperatureHumidityChart
+
+ val temperatures = lm.sortedBy { p -> p.order_id }
+ .map { m -> Pair(m.temperature, m.timestamp) }
+ val humidities = lm.sortedBy { p -> p.order_id }
+ .map { m -> Pair(m.humidity, m.timestamp) }
+
+ // Ajouter des points de données (exemples)
+ val temperatureEntries = temperatures.map { pair ->
+ Entry((pair.second.time).toFloat(), pair.first) // (timestamp, température)
+ }
+
+ val humidityEntries = humidities.map { pair ->
+ Entry((pair.second.time).toFloat(), pair.first) // (timestamp, humidité)
+ }
+
+ // Créer des LineDataSet pour chaque série de données
+ val temperatureDataSet = LineDataSet(temperatureEntries, "Température")
+ val humidityDataSet = LineDataSet(humidityEntries, "Hygrométrie")
+ Log.i("ProjectActivity", temperatureEntries.toString())
+ val minX = temperatureEntries.minOf { it.x } // La valeur minimale de x
+ val maxX = temperatureEntries.maxOf { it.x } // La valeur maximale de x
+ val xAxis = temperatureHumidityChart.xAxis
+ xAxis.valueFormatter = object : ValueFormatter() {
+ override fun getFormattedValue(value: Float): String {
+ val date = Date(value.toLong())
+ val sdf = SimpleDateFormat("hh:mm", Locale.getDefault())
+ return sdf.format(date)
+ }
+ }
+ xAxis.axisMinimum = minX
+ xAxis.axisMaximum = maxX
+ // Ajouter les datasets au graphique
+ val dataSets: MutableList = ArrayList()
+ dataSets.add(temperatureDataSet)
+ dataSets.add(humidityDataSet)
+ // val lineData = LineData(temperatureDataSet, humidityDataSet)
+ //Log.e("Graph", lineData.getDataSetByIndex(0).entryCount.toString())
+ temperatureHumidityChart.data = LineData(dataSets)
+
+
+ // Personnaliser le graphique (par exemple, couleur, légende, etc.)
+ temperatureDataSet.color = Color.RED
+ humidityDataSet.color = Color.BLUE
+
+ temperatureHumidityChart.invalidate() // Rafraîchir le graphique
+ }
+
+ fun initProjectInfo(){
+ val nameview = findViewById(R.id.project_name)
+ val descriptionview = findViewById(R.id.project_description)
+ val beginview = findViewById(R.id.project_start_date)
+ val statusview = findViewById(R.id.project_status)
+
+ nameview.text = project!!.name
+ descriptionview.text = project!!.description
+ beginview.text = project!!.start_date.toString()
+ statusview.text = project!!.getStatusText()
+ }
}
diff --git a/app/src/main/java/com/dreamteam/timelapse/ProjectAdapter.kt b/app/src/main/java/com/dreamteam/timelapse/ProjectAdapter.kt
index 3bbde6b..67bbcdb 100644
--- a/app/src/main/java/com/dreamteam/timelapse/ProjectAdapter.kt
+++ b/app/src/main/java/com/dreamteam/timelapse/ProjectAdapter.kt
@@ -11,8 +11,12 @@ import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
+import com.dreamteam.timelapse.data.Project
class ProjectAdapter(private val projects: List, private val listener: OnEmptyStateListener) : RecyclerView.Adapter() {
+ init{
+ listener.onEmptyStateChanged(projects.isEmpty())
+ }
interface OnEmptyStateListener {
fun onEmptyStateChanged(isEmpty: Boolean)
@@ -30,7 +34,6 @@ class ProjectAdapter(private val projects: List, private val listener:
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_project_card, parent, false)
//projects.isEmpty()
- listener.onEmptyStateChanged(projects.isEmpty())
return ProjectViewHolder(view)
}
diff --git a/app/src/main/java/com/dreamteam/timelapse/ProjetsFrag.kt b/app/src/main/java/com/dreamteam/timelapse/ProjetsFrag.kt
index f73f739..cf4bdd1 100644
--- a/app/src/main/java/com/dreamteam/timelapse/ProjetsFrag.kt
+++ b/app/src/main/java/com/dreamteam/timelapse/ProjetsFrag.kt
@@ -2,20 +2,17 @@ package com.dreamteam.timelapse
import android.os.Bundle
import android.util.Log
+import android.util.TypedValue
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.ListView
-import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.dreamteam.timelapse.data.ProjectRepository
import com.dreamteam.timelapse.databinding.FragmentProjetsBinding
-import com.dreamteam.timelapse.databinding.FragmentVideosBinding
-import kotlinx.coroutines.delay
import com.dreamteam.timelapse.data.ApiService
+import com.dreamteam.timelapse.data.Project
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
@@ -50,11 +47,11 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- Log.d("ProjetsFrag", "Fragment Projets créé")
_binding = FragmentProjetsBinding.inflate(inflater, container, false)
+ Log.d("ProjetsFrag", "Fragment Projets créé")
projectRepository = ProjectRepository(apiService) // Tu initialises ton repository
- fetchProjects()
+ //fetchProjects()
return _binding?.root
}
@@ -68,6 +65,7 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
fetchProjects()
Log.d("ProjetsFrag", "Actualisation des projets")
}
+ fetchProjects()
recyclerView = binding.recyclerView // view.findViewById(R.id.recyclerView)
recyclerView.layoutManager = LinearLayoutManager(context)
@@ -77,8 +75,11 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
private fun fetchProjects() {
// Simulez l'appel API
- binding.swipeRefreshLayout.isRefreshing = true
+ binding.swipeRefreshLayout.setEnabled(true)
+ binding.swipeRefreshLayout.setRefreshing(true)
+ //binding.swipeRefreshLayout.
+ //binding.swipeRefreshLayout.dragDown()
Log.d("ProjetsFrag", "User has refreshed the projects list")
projectRepository.fetchProjects(
onSuccess = { projects ->
@@ -89,7 +90,12 @@ class ProjetsFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
// Mettre à jour le RecyclerView ou autre traitement
},
onError = { errorMessage ->
- Log.e("ProjetsFrag", errorMessage)
+ Log.e("ProjetsFrag prout", errorMessage)
+ //onEmptyStateChanged(true)
+ this.projects = listOf()
+ this.projectAdapter = ProjectAdapter(this.projects, this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir)
+ this.recyclerView.adapter = this.projectAdapter
+
}
)
binding.swipeRefreshLayout.isRefreshing = false
diff --git a/app/src/main/java/com/dreamteam/timelapse/TabsAdapter.kt b/app/src/main/java/com/dreamteam/timelapse/TabsAdapter.kt
index f425858..599a8a7 100644
--- a/app/src/main/java/com/dreamteam/timelapse/TabsAdapter.kt
+++ b/app/src/main/java/com/dreamteam/timelapse/TabsAdapter.kt
@@ -17,4 +17,5 @@ class TabsAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) {
else -> ProjetsFrag() // Par défaut
}
}
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/dreamteam/timelapse/VideoFrag.kt b/app/src/main/java/com/dreamteam/timelapse/VideoFrag.kt
index 8824bc9..4204ac2 100644
--- a/app/src/main/java/com/dreamteam/timelapse/VideoFrag.kt
+++ b/app/src/main/java/com/dreamteam/timelapse/VideoFrag.kt
@@ -1,44 +1,112 @@
package com.dreamteam.timelapse
import android.os.Bundle
+import android.util.Log
+import android.util.TypedValue
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.navigation.fragment.findNavController
-import com.dreamteam.timelapse.databinding.FragmentVideosBinding
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.dreamteam.timelapse.data.ProjectRepository
+import com.dreamteam.timelapse.databinding.FragmentProjetsBinding
+import com.dreamteam.timelapse.data.ApiService
+import com.dreamteam.timelapse.data.Project
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
/**
- * A simple [Fragment] subclass as the second destination in the navigation.
+ * A simple [Fragment] subclass as the default destination in the navigation.
*/
-class VideoFrag : Fragment() {
- private var _binding: FragmentVideosBinding? = null
+class VideoFrag : Fragment(), ProjectAdapter.OnEmptyStateListener {
- // This property is only valid between onCreateView and
- // onDestroyView.
+ private lateinit var projectRepository: ProjectRepository
+ //private lateinit var listView: ListView
+ private lateinit var recyclerView: RecyclerView
+ private lateinit var projectAdapter: ProjectAdapter
+ private var _binding: FragmentProjetsBinding? = null
private val binding get() = _binding!!
+ private lateinit var apiService: ApiService // Déclare l'apiService
+ private var projects: List = emptyList() // Déclare une liste de projets vide
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ // Initialiser apiService ici, par exemple, en utilisant Retrofit
+ val retrofit = Retrofit.Builder()
+ .baseUrl("https://timelapse.kerboul.me/api/")
+ .addConverterFactory(GsonConverterFactory.create())
+ .build()
+
+ apiService = retrofit.create(ApiService::class.java) // Crée une instance d'ApiService
+ }
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
- ): View {
+ ): View? {
+ _binding = FragmentProjetsBinding.inflate(inflater, container, false)
+ Log.d("ProjetsFrag", "Fragment Projets créé")
- _binding = FragmentVideosBinding.inflate(inflater, container, false)
- return binding.root
+ projectRepository = ProjectRepository(apiService) // Tu initialises ton repository
+ //fetchProjects()
+ 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)
+ val swipeRefreshLayout = binding.swipeRefreshLayout
+
+ swipeRefreshLayout.setOnRefreshListener {
+ fetchProjects()
+ Log.d("ProjetsFrag", "Actualisation des projets")
+ }
+ fetchProjects()
+
+ recyclerView = binding.recyclerView // view.findViewById(R.id.recyclerView)
+ recyclerView.layoutManager = LinearLayoutManager(context)
+
+
+ }
+
+ private fun fetchProjects() {
+ // Simulez l'appel API
+ binding.swipeRefreshLayout.setEnabled(true)
+ binding.swipeRefreshLayout.setRefreshing(true)
+ //binding.swipeRefreshLayout.
+
+ //binding.swipeRefreshLayout.dragDown()
+ Log.d("ProjetsFrag", "User has refreshed the projects list")
+ projectRepository.fetchProjects(
+ onSuccess = { projects ->
+ Log.d("ProjetsFrag", "Projets reçus : $projects")
+ this.projects = projects
+ this.projectAdapter = ProjectAdapter(this.projects, this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir)
+ this.recyclerView.adapter = this.projectAdapter
+ // Mettre à jour le RecyclerView ou autre traitement
+ },
+ onError = { errorMessage ->
+ Log.e("ProjetsFrag prout", errorMessage)
+ //onEmptyStateChanged(true)
+ this.projects = listOf()
+ this.projectAdapter = ProjectAdapter(this.projects, this) //TODO : Potentiel problème pour les refresh ici (update de l'adapter ou un truc du genre à voir)
+ this.recyclerView.adapter = this.projectAdapter
+
+ }
+ )
+ binding.swipeRefreshLayout.isRefreshing = false
+ }
+ override fun onEmptyStateChanged(isEmpty: Boolean) {
+ // Afficher ou masquer le message
+ if (isEmpty) {
+ binding.noProjectsText.visibility = View.VISIBLE
+ } else {
+ binding.noProjectsText.visibility = View.GONE
}
}
- override fun onDestroyView() {
- super.onDestroyView()
- _binding = null
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/dreamteam/timelapse/data/ApiService.kt b/app/src/main/java/com/dreamteam/timelapse/data/ApiService.kt
index 5c04648..32a33f5 100644
--- a/app/src/main/java/com/dreamteam/timelapse/data/ApiService.kt
+++ b/app/src/main/java/com/dreamteam/timelapse/data/ApiService.kt
@@ -1,12 +1,19 @@
package com.dreamteam.timelapse.data
-import com.dreamteam.timelapse.Project
import retrofit2.Call
+import retrofit2.http.Body
+import retrofit2.http.Field
+import retrofit2.http.FormUrlEncoded
import retrofit2.http.GET
+import retrofit2.http.POST
import retrofit2.http.Path
interface ApiService {
- @GET("projects") // Remplace par l'endpoint de ton API
+ @GET("projects")
fun getProjets(): Call>
- @GET("projects/{id}") // Remplace par l'endpoint de ton API
+ @GET("projects/{id}")
fun getProjet(@Path("id") projectId: Int): Call
+ @GET("projects/{id}/measurements") // Remplace par l'endpoint de ton API
+ fun getMeasurements(@Path("id") projectId: Int): Call>
+ @POST("projects/")
+ fun createProject(@Body project: Project): Call
}
\ No newline at end of file
diff --git a/app/src/main/java/com/dreamteam/timelapse/data/Confirmation.kt b/app/src/main/java/com/dreamteam/timelapse/data/Confirmation.kt
new file mode 100644
index 0000000..03efc2d
--- /dev/null
+++ b/app/src/main/java/com/dreamteam/timelapse/data/Confirmation.kt
@@ -0,0 +1,8 @@
+package com.dreamteam.timelapse.data
+
+data class Confirmation (
+ val message: String,
+ val id: Int
+){
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/dreamteam/timelapse/data/Measurement.kt b/app/src/main/java/com/dreamteam/timelapse/data/Measurement.kt
new file mode 100644
index 0000000..7a88cef
--- /dev/null
+++ b/app/src/main/java/com/dreamteam/timelapse/data/Measurement.kt
@@ -0,0 +1,14 @@
+package com.dreamteam.timelapse.data
+
+import java.util.Date
+
+data class Measurement(
+ val id: Int,
+ val project_id: Int,
+ val timestamp: Date,
+ val path: String,
+ val temperature: Float,
+ val humidity: Float,
+ val order_id: Int
+) {
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/dreamteam/timelapse/Project.kt b/app/src/main/java/com/dreamteam/timelapse/data/Project.kt
similarity index 90%
rename from app/src/main/java/com/dreamteam/timelapse/Project.kt
rename to app/src/main/java/com/dreamteam/timelapse/data/Project.kt
index c620a8a..5a4370f 100644
--- a/app/src/main/java/com/dreamteam/timelapse/Project.kt
+++ b/app/src/main/java/com/dreamteam/timelapse/data/Project.kt
@@ -1,71 +1,74 @@
-package com.dreamteam.timelapse
-
-import android.os.Parcel
-import android.os.Parcelable
-import java.util.Date
-
-//{
-// "id": 1,
-// "creation": "2024-10-24T13:46:04.513Z",
-// "status": "test",
-// "description": "Projet de Test",
-// "titre": "Test Project"
-//}
-data class Project(
- val id: Int,
- val name: String,
- val description: String,
- val start_date: Date,
- val status: Int,
- val thumbnail_url: String?
-) : Parcelable {
-
- fun getStatusText(): String{
- val statusArr = arrayOf("Brouillon", "En Cours", "Terminé", "Annulé")
- return statusArr[status]
- }
- fun getStatusColor(): Int{
- return when (status) {
- 0 -> R.color.brouillon
- 1 -> R.color.en_cours
- 2 -> R.color.termine
- 3 -> R.color.annule
- else -> R.color.default_badge
- }
- }
-
- // Constructor to recreate from Parcel
- constructor(parcel: Parcel) : this(
- parcel.readInt(),
- parcel.readString() ?: "",
- parcel.readString() ?: "",
- Date(parcel.readLong()),
- parcel.readInt(),
- parcel.readString()
- )
-
- // Write object to Parcel
- override fun writeToParcel(parcel: Parcel, flags: Int) {
- parcel.writeInt(id)
- parcel.writeString(name)
- parcel.writeString(description)
- parcel.writeString(start_date.toString())
- parcel.writeInt(status)
- }
-
- // Describe the contents of the Parcel
- override fun describeContents(): Int = 0
-
- companion object CREATOR : Parcelable.Creator {
- override fun createFromParcel(parcel: Parcel): Project {
- return Project(parcel)
- }
-
- override fun newArray(size: Int): Array {
- return arrayOfNulls(size)
- }
- }
-// fun getThumbnail(): String {
-// return images[0]
-// }
-}
+package com.dreamteam.timelapse.data
+
+import android.os.Parcel
+import android.os.Parcelable
+import android.util.Log
+import com.dreamteam.timelapse.R
+import java.util.Date
+
+//{
+// "id": 1,
+// "creation": "2024-10-24T13:46:04.513Z",
+// "status": "test",
+// "description": "Projet de Test",
+// "titre": "Test Project"
+//}
+data class Project(
+ val id: Int,
+ val name: String,
+ val description: String,
+ val start_date: Date,
+ val status: Int,
+ val thumbnail_url: String?
+) : Parcelable {
+
+ fun getStatusText(): String{
+ Log.i("Project", "Status $status being trasnlated")
+ val statusArr = arrayOf("Brouillon", "En Cours", "Terminé", "Annulé")
+ return statusArr[status]
+ }
+ fun getStatusColor(): Int{
+ return when (status) {
+ 0 -> R.color.brouillon
+ 1 -> R.color.en_cours
+ 2 -> R.color.termine
+ 3 -> R.color.annule
+ else -> R.color.default_badge
+ }
+ }
+
+ // Constructor to recreate from Parcel
+ constructor(parcel: Parcel) : this(
+ parcel.readInt(),
+ parcel.readString() ?: "",
+ parcel.readString() ?: "",
+ Date(parcel.readLong()),
+ parcel.readInt(),
+ parcel.readString()
+ )
+
+ // Write object to Parcel
+ override fun writeToParcel(parcel: Parcel, flags: Int) {
+ parcel.writeInt(id)
+ parcel.writeString(name)
+ parcel.writeString(description)
+ parcel.writeLong(start_date.time)
+ parcel.writeInt(status)
+ }
+
+ // Describe the contents of the Parcel
+ override fun describeContents(): Int = 0
+
+ companion object CREATOR : Parcelable.Creator {
+ override fun createFromParcel(parcel: Parcel): Project {
+ return Project(parcel)
+ }
+
+ override fun newArray(size: Int): Array {
+ return arrayOfNulls(size)
+ }
+ }
+// fun getThumbnail(): String {
+// return images[0]
+// }
+}
diff --git a/app/src/main/java/com/dreamteam/timelapse/data/ProjectRepository.kt b/app/src/main/java/com/dreamteam/timelapse/data/ProjectRepository.kt
index 705ac57..eccad4b 100644
--- a/app/src/main/java/com/dreamteam/timelapse/data/ProjectRepository.kt
+++ b/app/src/main/java/com/dreamteam/timelapse/data/ProjectRepository.kt
@@ -1,9 +1,9 @@
package com.dreamteam.timelapse.data
-import com.dreamteam.timelapse.Project
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
+import java.util.Date
class ProjectRepository(private val apiService: ApiService) {
@@ -26,4 +26,41 @@ class ProjectRepository(private val apiService: ApiService) {
}
})
}
+
+ fun fetchMeasurementsOfProject(pid: Int, onSuccess: (List) -> Unit, onError: (String) -> Unit) {
+ val call = apiService.getMeasurements(pid)
+ call.enqueue(object : Callback> {
+ override fun onResponse(call: Call>, response: Response>) {
+ if (response.isSuccessful) {
+ val measures = response.body()
+ measures?.let {
+ onSuccess(it)
+ } ?: onError("Aucune mesure trouvé")
+ } else {
+ onError("Erreur : ${response.code()}")
+ }
+ }
+
+ override fun onFailure(call: Call>, t: Throwable) {
+ onError("Échec de l'appel API : ${t.message}")
+ }
+ })
+ }
+ fun createProject(name: String, description: String, onSuccess: () -> Unit, onError: (String) -> Unit) {
+ val call = apiService.createProject(Project(0, name, description, Date(), 0, null))
+ call.enqueue(object : Callback {
+ override fun onResponse(call: Call, response: Response) {
+ if (response.isSuccessful) {
+ onSuccess()
+ } else {
+ onError("Erreur : ${response.code()}")
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ onError("Échec de l'appel API : ${t.message}")
+ }
+ })
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/dreamteam/timelapse/data/Video.kt b/app/src/main/java/com/dreamteam/timelapse/data/Video.kt
new file mode 100644
index 0000000..8e65ed9
--- /dev/null
+++ b/app/src/main/java/com/dreamteam/timelapse/data/Video.kt
@@ -0,0 +1,12 @@
+package com.dreamteam.timelapse.data
+
+data class Video (
+ val id: Int,
+ val project_id: Int,
+ val measurement_ids: List,
+ val video_file: String?,
+ val resolution:String,
+ val duration: Int,
+ val status: Int, //0 pas fini, 1 fini
+ val name: String
+){}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 307b3c5..f0a2ad9 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -4,7 +4,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
- tools:context=".MainActivity">
+ tools:context=".MainActivity"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
-->
-
+ app:srcCompat="@android:drawable/ic_input_add" />
diff --git a/app/src/main/res/layout/item_image.xml b/app/src/main/res/layout/item_image.xml
new file mode 100644
index 0000000..d996c76
--- /dev/null
+++ b/app/src/main/res/layout/item_image.xml
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/project.xml b/app/src/main/res/layout/project.xml
index bfeca0a..da97408 100644
--- a/app/src/main/res/layout/project.xml
+++ b/app/src/main/res/layout/project.xml
@@ -31,90 +31,125 @@
-
-
-
-
+
-
-
+
-
-
-
-
+
-
+
-
-
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/project_create_dialog_layout.xml b/app/src/main/res/layout/project_create_dialog_layout.xml
new file mode 100644
index 0000000..30d0ab0
--- /dev/null
+++ b/app/src/main/res/layout/project_create_dialog_layout.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file