- 상점
- 방
+ 상점
+ 방
- {/*
-
*/}
도토리: {dotory.value}
diff --git a/src/routes/[username]/(store)/room/index.tsx b/src/routes/[username]/(store)/room/index.tsx
index 880930b..367b442 100644
--- a/src/routes/[username]/(store)/room/index.tsx
+++ b/src/routes/[username]/(store)/room/index.tsx
@@ -1,4 +1,4 @@
-import { $, component$, useSignal, useTask$, useVisibleTask$ } from "@builder.io/qwik";
+import { $, component$, useSignal, useVisibleTask$} from "@builder.io/qwik";
import { DocumentHead } from "@builder.io/qwik-city";
import RoomGrid from "~/components/room/RoomGrid";
import { typechecker } from "~/utils/func";
@@ -11,22 +11,28 @@ interface Furniture {
x : number;
y : number;
}
-interface Avatar {
- id: number;
- user_id: number;
- avatar_type: {
- name: string;
- path: string
- },
- top_clothe_type: {
- name: string;
- path: string
- },
- bottom_clothe_type: {
- name: string;
- path: string
- }
+interface SendFurniture {
+
+ name: string;
+ image_path : string;
+
}
+// interface Avatar {
+// id: number;
+// user_id: number;
+// avatar_type: {
+// name: string;
+// path: string
+// },
+// top_clothe_type: {
+// name: string;
+// path: string
+// },
+// bottom_clothe_type: {
+// name: string;
+// path: string
+// }
+// }
interface SetAvatarType {
avatar_type: string;
top_clothe_type: string;
@@ -37,47 +43,26 @@ interface RoomType {
image_path: string;
}
-interface Room {
- id: number;
- user_id: number;
- room_type: string;
- room_name: string;
- room_image_path: string;
-}
+// interface Room {
+// id: number;
+// user_id: number;
+// room_type: string;
+// room_name: string;
+// room_image_path: string;
+// }
export const useRoomLoader = routeLoader$(async ({cookie}) => {
+ const headers = {
+ Authorization: `Bearer ${cookie.get("access_token")?.value}`,
+ }
try {
- const myRoom = await axios.get("http://localhost:8000/api/room/layout", {
- headers: {
- Authorization: `Bearer ${cookie.get("access_token")?.value}`,
- },
- })
- const myAvatar = await axios.get("http://localhost:8000/api/avatar", {
- headers: {
- Authorization: `Bearer ${cookie.get("access_token")?.value}`,
- },
- })
- const roomType = await axios.get("http://localhost:8000/api/room/types", {
- headers: {
- Authorization: `Bearer ${cookie.get("access_token")?.value}`,
- },
- })
- const furniture = await axios.get("http://localhost:8000/api/room/my", {
- headers: {
- Authorization: `Bearer ${cookie.get("access_token")?.value}`,
- },
- })
- const avatarType = await axios.get("http://localhost:8000/api/avatar/options", {
- headers: {
- Authorization: `Bearer ${cookie.get("access_token")?.value}`,
- },
- })
- const roomTypeData = roomType.data;
- const avatar : Avatar = myAvatar.data;
- const room : Room = myRoom.data;
- const furnitureData = furniture.data;
- const avatarTypeData = avatarType.data;
- console.log(myRoom.data);
- return {myData : {room: room, avatar: avatar}, selectionData: {roomType: roomTypeData, furniture: furnitureData, avatarType: avatarTypeData}};
+ const [myRoom, myAvatar, roomType, furniture, avatarType] = await Promise.all([
+ axios.get("http://localhost:8000/api/room/layout", { headers }),
+ axios.get("http://localhost:8000/api/avatar", { headers }),
+ axios.get("http://localhost:8000/api/room/types", { headers }),
+ axios.get("http://localhost:8000/api/room/my", { headers }),
+ axios.get("http://localhost:8000/api/avatar/options", { headers }),
+ ]);
+ return {myData : {room: myRoom.data, avatar: myAvatar.data}, selectionData: {roomType: roomType.data, furniture: furniture.data, avatarType: avatarType.data}};
} catch (error : any) {
console.error(error);
return error.response?.data?.detail || 'Room not found';
@@ -85,123 +70,186 @@ export const useRoomLoader = routeLoader$(async ({cookie}) => {
})
export default component$(() => {
const data = useRoomLoader();
- const selectedFurniture = useSignal
([]); // 유저 선택 가구
- const selectedType = useSignal("furniture"); // 헤더에서 가구, 아바타, 배경 구분
+ // const navigate = useNavigate();
+ const reloadPage = $(() => {
+ window.location.reload();
+ });
+ // 1. 소유한 가구 데이터 (layout API에서 가져옴)
+ const ownedFurnitures = useSignal([]);
+ // 2. 현재 배치된 가구 데이터 (room/my API에서 가져옴)
+ const placedFurnitures = useSignal([]);
+ // 3. 현재 선택된 가구 (새로 배치하려는 가구만) - 제거
+ // const selectedFurniture = useSignal(null);
+
+ const selectedType = useSignal<"furniture" | "avatar" | "background">("furniture");
+ // const editingPosition = useSignal(null);
const selectedRoomType = useSignal("room_1");
const selectedAvatar = useSignal({
avatar_type: "",
top_clothe_type: "",
bottom_clothe_type: ""
});
- useVisibleTask$(() => {
+ const mergedFurnitures = useSignal([] as Furniture[]);
+ // 오류 상태 관리
+ const errorMessage = useSignal("");
+ const successMessage = useSignal("");
+ useVisibleTask$(async () => {
+ // 기본 데이터 설정
selectedRoomType.value = data.value.myData.room.room.room_type;
selectedAvatar.value.avatar_type = data.value.myData.avatar.avatar_type.name;
selectedAvatar.value.top_clothe_type = data.value.myData.avatar.top_clothe_type.name;
selectedAvatar.value.bottom_clothe_type = data.value.myData.avatar.bottom_clothe_type.name;
-
+ ownedFurnitures.value = data.value.selectionData.furniture;
+ placedFurnitures.value = [...data.value.myData.room.furniture];
+ mergedFurnitures.value = ownedFurnitures.value.map(o => {
+ const placed = placedFurnitures.value.find(p => p.furniture_name === o.name);
+ return placed
+ ? placed
+ : {
+ furniture_name: o.name,
+ image_path: o.image_path,
+ x: -1,
+ y: -1,
+ };
+ });
+
})
- const deleteFurniture = $((selectedFurniture : Furniture) => {
- const furnitureRes = axios.delete("http://localhost:8000/api/room/furniture", {
- data: {
- furniture_name: selectedFurniture.furniture_name,
- x: selectedFurniture.x,
- y: selectedFurniture.y,
- },
- headers: {
- Authorization: `Bearer ${getCookie("access_token")}`,
- },
- })
- })
- // const getNewState = async () => {
- // const myRoom = await axios.get("http://localhost:8000/api/room/layout", {
- // headers: {
- // Authorization: `Bearer ${getCookie("access_token")}`,
- // },
- // })
- // const myAvatar = await axios.get("http://localhost:8000/api/avatar", {
- // headers: {
- // Authorization: `Bearer ${getCookie("access_token")}`,
- // },
- // })
- // const roomType = await axios.get("http://localhost:8000/api/room/types", {
- // headers: {
- // Authorization: `Bearer ${getCookie("access_token")}`,
- // },
- // })
- // const furniture = await axios.get("http://localhost:8000/api/room/my", {
- // headers: {
- // Authorization: `Bearer ${getCookie("access_token")}`,
- // },
- // })
- // const avatarType = await axios.get("http://localhost:8000/api/avatar/options", {
- // headers: {
- // Authorization: `Bearer ${getCookie("access_token")}`,
- // },
- // })
- // const roomTypeData = roomType.data;
- // const avatar : Avatar = myAvatar.data.avatar;
- // const room : Room = myRoom.data;
- // const furnitureData = furniture.data;
- // const avatarTypeData = avatarType.data;
- // console.log(myRoom.data);
- // }
- const handleChange = $( async () => {
- console.log("handleChange");
+ // 가구 배치 함수
+ const placeFurniture = $(async (furniture: Furniture, x: number, y: number) => {
try {
- // 배경 설정
- console.log(selectedRoomType.value);
- const roomRes = await axios.patch("http://localhost:8000/api/room/",
- {
- type: selectedRoomType.value
- },
- {
- headers: {
- Authorization: `Bearer ${getCookie("access_token")}`,
- },
- }
- );
- const avatarRes = await axios.put("http://localhost:8000/api/avatar", {
-
- avatar_type: selectedAvatar.value.avatar_type,
- top_clothe_type: selectedAvatar.value.top_clothe_type,
- bottom_clothe_type: selectedAvatar.value.bottom_clothe_type,
- },
- {
- headers: {
- Authorization: `Bearer ${getCookie("access_token")}`,
- },
- }
- );
- // for (let i = 0; i < selectedFurniture.value.length; i++) {
- // const furnitureRes = await axios.post("http://localhost:8000/api/room/furniture", {
- // furniture_name: selectedFurniture.value[i].furniture_name,
- // x: selectedFurniture.value[i].x,
- // y: selectedFurniture.value[i].y,
- // },
- // {
- // headers: {
- // Authorization: `Bearer ${getCookie("access_token")}`,
- // },
- // })
- // }
- // getNewState();
- console.log(roomRes.data);
- console.log(avatarRes.data);
- } catch (error) {
- console.log(error);
+ await axios.post("http://localhost:8000/api/room/furniture", {
+ furniture_name: furniture.furniture_name,
+ x: x,
+ y: y
+ }, {
+ headers: { Authorization: `Bearer ${getCookie("access_token")}` }
+ });
+
+ // 성공 시 placedFurnitures에 추가
+ if (!mergedFurnitures.value.find(f => f.furniture_name === furniture.furniture_name)) {
+ mergedFurnitures.value = Array.from(new Set([
+ ...mergedFurnitures.value,
+ {
+ furniture_name: furniture.furniture_name, // SendFurniture has 'name' property
+ image_path: furniture.image_path,
+ x: x,
+ y: y
+ }
+ ]));
+
+ placedFurnitures.value = Array.from(new Set([...placedFurnitures.value, furniture]));
+ }
+ else {
+ mergedFurnitures.value =Array.from(new Set([...mergedFurnitures.value]));
+ placedFurnitures.value = Array.from(new Set([...placedFurnitures.value]));
+ }
+ console.log('Placed fu rniture:', mergedFurnitures.value);
+
+ return true;
+ } catch (error: any) {
+ console.error('가구 배치 실패:', error);
+ errorMessage.value = error.response.data.detail;
+ setTimeout(() => { errorMessage.value = ""; }, 10000);
+ return false;
}
- })
- const handleCancel = $(() => {
- console.log("handleCancel");
+ });
+
+ // 가구 제거 함수
+ const removeFurniture = $(async (furniture: Furniture) => {
+ console.log(furniture + " furniture");
+ try {
+ await axios.delete(`http://localhost:8000/api/room/furniture?x=${furniture.x}&y=${furniture.y}&furniture_name=${furniture.furniture_name}`, {
+ headers: { Authorization: `Bearer ${getCookie("access_token")}` }
+ });
+
+ placedFurnitures.value = Array.from(new Set([...placedFurnitures.value.filter(f =>
+ f.furniture_name !== furniture.furniture_name && (f.x !== furniture.x || f.y !== furniture.y)
+ )]));
+ mergedFurnitures.value = Array.from(new Set([...mergedFurnitures.value.map(f =>
+ f.furniture_name === furniture.furniture_name
+ ? { ...f, x: -1, y: -1 }
+ : f
+ )]));
+ return true;
+ } catch (error: any) {
+ console.error('가구 제거 실패:', error);
+ errorMessage.value = `${furniture.furniture_name} 제거에 실패했습니다.`;
+ setTimeout(() => { errorMessage.value = ""; }, 10000);
+ return false;
+ }
+ });
+
+ // 가구 위치 업데이트 함수
+ const updateFurniturePosition = $(async (furniture:Furniture, newX: number, newY: number) => {
+ if ((newX < 0 || newX >= 10) || (newY < 0 || newY >= 10)) {
+ errorMessage.value = "위치가 이상합니다.";
+ console.log(newX, newY);
+ setTimeout(() => { errorMessage.value = ""; }, 10000);
+ return false;
+ }
+ try {
+
+ const foundedFurniture = mergedFurnitures.value.find(f => f.x === newX && f.y === newY)
+ if (foundedFurniture) {
+ await removeFurniture(foundedFurniture);
+ }
+ //같은 이름으 가구가 이미 있나
+ console.log(placedFurnitures.value, furniture + " furniture");
+ const foundedFurniture2 = placedFurnitures.value.find(f => f.furniture_name === furniture.furniture_name)
+ if (foundedFurniture2) {
+ await removeFurniture(foundedFurniture2);
+ }
+ // 새 위치에 가구 배치
+ console.log(furniture + " 가구 움직임");
+ await placeFurniture(furniture, newX, newY);
+
+ return true;
+ } catch (error: any) {
+ console.error('가구 위치 업데이트 실패:', error);
+ return false;
+ }
+
+ });
+
+
+ const handleChange = $( async () => {
+ try {
+ await axios.patch("http://localhost:8000/api/room/", {type: selectedRoomType.value}, {headers: {Authorization: `Bearer ${getCookie("access_token")}`}});
+ await axios.put("http://localhost:8000/api/avatar", {avatar_type: selectedAvatar.value.avatar_type,top_clothe_type: selectedAvatar.value.top_clothe_type,bottom_clothe_type: selectedAvatar.value.bottom_clothe_type,}, {headers: {Authorization: `Bearer ${getCookie("access_token")}`}});
+
+ } catch (error) {console.log(error);}
})
return (
-
내 방 꾸미기
+
+
내 방 꾸미기
+
+ {/* 오류 메시지 표시 */}
+ {errorMessage.value && (
+
+ {errorMessage.value?errorMessage.value:" "}
+
+ )}
+
+ {/* 성공 메시지 표시 */}
+ {successMessage.value && (
+
+ {successMessage.value?successMessage.value:" "}
+
+ )}
+
+
+
{/* Room Preview */}
@@ -251,13 +299,88 @@ export default component$(() => {
{selectedType.value === "furniture" ? (
- data.value.selectionData.furniture.map((furniture: Furniture) => (
-
{if(selectedFurniture.value.includes(furniture)) selectedFurniture.value = selectedFurniture.value.filter((item: Furniture) => item !== furniture); else selectedFurniture.value.push(furniture);}}>
-

-
{furniture.furniture_name}
+
+ {/* 배치된 가구 목록 - 각각 입력창 표시 */}
+
+ {mergedFurnitures.value.map((furniture: Furniture) => (
+
+
+

+
+
+ {furniture.furniture_name}
+
+ {furniture.x !== -1 && furniture.y !== -1 && (
+
+ 현재 위치: ({furniture.x}, {furniture.y})
+
+ )}
+
+ {furniture.x !== -1 && furniture.y !== -1 && (
+
+ )
+ }
+
+
+ {/* 위치 수정 입력창 */}
+
+
+ {
+ furniture.x = parseInt((e.target as HTMLInputElement).value);
+ }
+ }
+ class="w-16 px-2 py-1 text-center border rounded"
+ />
+
+ {
+ furniture.y = parseInt((e.target as HTMLInputElement).value);
+ }
+ }
+ class="w-16 px-2 py-1 text-center border rounded"
+ />
+
+
+
+
+ ))}
+
+ {/* 배치된 가구가 없을 때 */}
+ {ownedFurnitures.value.length === 0 && (
+
+
가구가 없습니다.
+
가구를 배치하려면 상점에서 가구를 구매하세요.
+
+ )}
- )))
- :
+
+ ) :
selectedType.value === "avatar" ? (
@@ -364,9 +487,14 @@ export default component$(() => {
{/*