Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions week2/.idea/deviceManager.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions week2/.idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions week2/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.compose.compiler)
id("kotlin-parcelize")
}

android {
Expand Down
37 changes: 37 additions & 0 deletions week2/app/src/main/java/com/example/week2/HomeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.week2.databinding.FragmentHomeBinding

class HomeFragment : Fragment() {
Expand All @@ -19,6 +21,41 @@ class HomeFragment : Fragment() {
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
}

private fun setupRecyclerView() {
val dummyProducts = listOf(
Product(1, "Air Jordan XXXVI", "Basketball Shoes", "US$185", R.drawable.img_air_jordan_xxxvi, category = "Basketball Shoes"),
Product(2, "Nike Air Force 1 '07", "Men's Shoes", "US$115", R.drawable.img_nike_air_force, category = "Men's Shoes"),
Product(3, "Nike Everyday Plus Cushioned", "Training Socks", "US$20", R.drawable.img_nike_everyday_plus_cushioned, category = "Training Socks")
)

val adapter = ProductAdapter(
dummyProducts,
onItemClick = { product ->
navigateToDetail(product)
},
onWishlistClick = { product, position ->
product.isWishlisted = !product.isWishlisted
binding.rvHomeProducts.adapter?.notifyItemChanged(position)
}
)

binding.rvHomeProducts.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
binding.rvHomeProducts.adapter = adapter
}

private fun navigateToDetail(product: Product) {
// Navigation Component를 사용하여 상세 화면으로 이동
val bundle = Bundle().apply {
putParcelable("product", product)
}
findNavController().navigate(R.id.action_homeFragment_to_productDetailFragment, bundle)
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
Expand Down
15 changes: 15 additions & 0 deletions week2/app/src/main/java/com/example/week2/Product.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.week2

import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class Product(
val id: Int,
val name: String,
val description: String,
val price: String,
val imageResId: Int,
var isWishlisted: Boolean = false,
val category: String = ""
) : Parcelable
45 changes: 45 additions & 0 deletions week2/app/src/main/java/com/example/week2/ProductAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.example.week2

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.week2.databinding.ItemProductBinding

class ProductAdapter(
private val products: List<Product>,
private val onItemClick: (Product) -> Unit,
private val onWishlistClick: (Product, Int) -> Unit
) : RecyclerView.Adapter<ProductAdapter.ProductViewHolder>() {

inner class ProductViewHolder(private val binding: ItemProductBinding) :
RecyclerView.ViewHolder(binding.root) {

fun bind(product: Product) {
binding.tvProductName.text = product.name
binding.tvProductDesc.text = product.description
binding.tvProductPrice.text = product.price
binding.ivProductImage.setImageResource(product.imageResId)

val heartRes = if (product.isWishlisted) {
R.drawable.ic_heart_fill
} else {
R.drawable.ic_heart_empty
}
binding.ibWishlist.setImageResource(heartRes)

binding.root.setOnClickListener { onItemClick(product) }
binding.ibWishlist.setOnClickListener { onWishlistClick(product, adapterPosition) }
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
val binding = ItemProductBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ProductViewHolder(binding)
}

override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
holder.bind(products[position])
}

override fun getItemCount(): Int = products.size
}
58 changes: 58 additions & 0 deletions week2/app/src/main/java/com/example/week2/ProductDetailFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.example.week2

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import com.example.week2.databinding.FragmentProductDetailBinding

class ProductDetailFragment : Fragment() {
private var _binding: FragmentProductDetailBinding? = null
private val binding get() = _binding!!

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentProductDetailBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

val product = arguments?.getParcelable<Product>("product")

product?.let {
binding.tvHeaderTitle.text = it.name
binding.ivDetailImage.setImageResource(it.imageResId)
binding.tvDetailCategory.text = it.category
binding.tvDetailName.text = it.name
binding.tvDetailPrice.text = it.price

updateWishlistButton(it.isWishlisted)
}

binding.ibBack.setOnClickListener {
findNavController().popBackStack()
}

binding.btnWishlist.setOnClickListener {
product?.let {
it.isWishlisted = !it.isWishlisted
updateWishlistButton(it.isWishlisted)
}
}
}

private fun updateWishlistButton(isWishlisted: Boolean) {
binding.ivWishlistHeart.isSelected = isWishlisted
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
38 changes: 38 additions & 0 deletions week2/app/src/main/java/com/example/week2/PurchaseFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import com.example.week2.databinding.FragmentPurchaseBinding

class PurchaseFragment : Fragment() {
Expand All @@ -19,6 +21,42 @@ class PurchaseFragment : Fragment() {
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
}

private fun setupRecyclerView() {
val dummyProducts = listOf(
Product(1, "Nike Everyday Plus Cushioned", "Training Crew Socks (6 Pairs)", "US$10", R.drawable.img_nike_everyday_plus_cushioned, category = "Training Crew Socks"),
Product(2, "Nike Elite Crew", "Basketball Socks", "US$16", R.drawable.img_training_ankle_socks, category = "Basketball Socks"),
Product(3, "Nike Air Force 1 '07", "Women's Shoes", "US$115", R.drawable.img_nike_air_force, category = "Women's Shoes"),
Product(4, "Jordan Nike Air Force 1 '07 Essentials", "Men's Shoes", "US$115", R.drawable.img_air_jordan_xxxvi, category = "Men's Shoes")
)

val adapter = ProductAdapter(
dummyProducts,
onItemClick = { product ->
navigateToDetail(product)
},
onWishlistClick = { product, position ->
product.isWishlisted = !product.isWishlisted
binding.rvPurchaseProducts.adapter?.notifyItemChanged(position)
}
)

binding.rvPurchaseProducts.layoutManager = GridLayoutManager(context, 2)
binding.rvPurchaseProducts.adapter = adapter
}

private fun navigateToDetail(product: Product) {
// Navigation Component를 사용하여 상세 화면으로 이동
val bundle = Bundle().apply {
putParcelable("product", product)
}
findNavController().navigate(R.id.action_purchaseFragment_to_productDetailFragment, bundle)
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
Expand Down
35 changes: 35 additions & 0 deletions week2/app/src/main/java/com/example/week2/WishlistFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import com.example.week2.databinding.FragmentWishlistBinding

class WishlistFragment : Fragment() {
Expand All @@ -19,6 +21,39 @@ class WishlistFragment : Fragment() {
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupRecyclerView()
}

private fun setupRecyclerView() {
// Dummy wishlist data
val dummyWishlist = mutableListOf(
Product(1, "Nike Everyday Plus Cushioned", "Training Ankle Socks (6 Pairs)", "US$16", R.drawable.img_training_ankle_socks, true),
Product(2, "Air Jordan XXXVI", "Basketball Shoes", "US$185", R.drawable.img_air_jordan_xxxvi, true)
)

val adapter = ProductAdapter(
dummyWishlist,
onItemClick = { product ->
Toast.makeText(context, "${product.name} clicked", Toast.LENGTH_SHORT).show()
},
onWishlistClick = { product, position ->
product.isWishlisted = !product.isWishlisted
// In wishlist fragment, usually removing from wishlist means removing from the list
if (!product.isWishlisted) {
dummyWishlist.removeAt(position)
binding.rvWishlistProducts.adapter?.notifyItemRemoved(position)
} else {
binding.rvWishlistProducts.adapter?.notifyItemChanged(position)
}
}
)

binding.rvWishlistProducts.layoutManager = GridLayoutManager(context, 2)
binding.rvWishlistProducts.adapter = adapter
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
Expand Down
6 changes: 6 additions & 0 deletions week2/app/src/main/res/drawable/bg_black_round.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/black" />
<corners android:radius="28dp" />
</shape>
9 changes: 9 additions & 0 deletions week2/app/src/main/res/drawable/bg_white_stroke.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/white" />
<stroke
android:width="1dp"
android:color="@android:color/darker_gray" />
<corners android:radius="28dp" />
</shape>
17 changes: 17 additions & 0 deletions week2/app/src/main/res/drawable/ic_caretleft.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<group>
<clip-path
android:pathData="M0,0h24v24h-24z"/>
<path
android:pathData="M15,19.5L7.5,12L15,4.5"
android:strokeLineJoin="round"
android:strokeWidth="2"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
</group>
</vector>
20 changes: 20 additions & 0 deletions week2/app/src/main/res/drawable/ic_heart_empty.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="34dp"
android:height="34dp"
android:viewportWidth="34"
android:viewportHeight="34">
<path
android:pathData="M17,17m-17,0a17,17 0,1 1,34 0a17,17 0,1 1,-34 0"
android:fillColor="#ffffff"/>
<group>
<clip-path
android:pathData="M7,7h20v20h-20z"/>
<path
android:strokeWidth="1"
android:pathData="M17,24.5L23.981,17.419C24.713,16.686 25.125,15.692 25.125,14.656C25.125,13.62 24.713,12.626 23.981,11.894C23.248,11.161 22.254,10.75 21.218,10.75C20.182,10.75 19.188,11.161 18.456,11.894L17,13.25L15.543,11.894C14.811,11.161 13.817,10.75 12.781,10.75C11.745,10.75 10.751,11.161 10.018,11.894C9.286,12.626 8.874,13.62 8.874,14.656C8.874,15.692 9.286,16.686 10.018,17.419L17,24.5Z"
android:strokeLineJoin="round"
android:fillColor="#00000000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
</group>
</vector>
23 changes: 23 additions & 0 deletions week2/app/src/main/res/drawable/ic_heart_fill.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="34dp"
android:height="34dp"
android:viewportWidth="34"
android:viewportHeight="34">
<path
android:pathData="M17,17m-17,0a17,17 0,1 1,34 0a17,17 0,1 1,-34 0"
android:fillColor="#ffffff"/>
<group>
<clip-path
android:pathData="M7,7h20v20h-20z"/>
<path
android:pathData="M7,7h20v20h-20z"
android:fillColor="#ffffff"/>
<path
android:strokeWidth="1"
android:pathData="M17,24.5L23.981,17.419C24.713,16.686 25.125,15.692 25.125,14.656C25.125,13.62 24.713,12.626 23.981,11.894C23.248,11.161 22.254,10.75 21.218,10.75C20.182,10.75 19.188,11.161 18.456,11.894L17,13.25L15.543,11.894C14.811,11.161 13.817,10.75 12.781,10.75C11.745,10.75 10.751,11.161 10.018,11.894C9.286,12.626 8.874,13.62 8.874,14.656C8.874,15.692 9.286,16.686 10.018,17.419L17,24.5Z"
android:strokeLineJoin="round"
android:fillColor="#FF0000"
android:strokeColor="#000000"
android:strokeLineCap="round"/>
</group>
</vector>
Loading