+
@@ -462,8 +636,9 @@ class ZzimManager {
const checkboxes = document.querySelectorAll('.market-checkbox-input');
checkboxes.forEach(checkbox => {
checkbox.addEventListener('change', (e) => {
- const marketIndex = parseInt(e.target.dataset.marketIndex);
- this.toggleMarketForZzim(marketIndex, e.target.checked);
+ const marketId = e.target.dataset.marketId;
+ const checkboxType = e.target.dataset.checkboxType;
+ this.toggleMarketCheckbox(marketId, checkboxType, e.target.checked);
});
});
@@ -471,8 +646,8 @@ class ZzimManager {
const editBtns = document.querySelectorAll('.market-edit-btn');
editBtns.forEach(btn => {
btn.addEventListener('click', (e) => {
- const marketIndex = parseInt(e.target.dataset.marketIndex);
- this.editMarket(marketIndex);
+ const marketId = e.target.dataset.marketId;
+ this.editMarket(marketId);
});
});
@@ -480,8 +655,8 @@ class ZzimManager {
const visibilityBtns = document.querySelectorAll('.market-visibility-btn');
visibilityBtns.forEach(btn => {
btn.addEventListener('click', (e) => {
- const marketIndex = parseInt(e.target.dataset.marketIndex);
- this.toggleMarketVisibility(marketIndex);
+ const marketId = e.target.dataset.marketId;
+ this.toggleMarketVisibility(marketId);
});
});
@@ -489,8 +664,8 @@ class ZzimManager {
const deleteBtns = document.querySelectorAll('.market-delete-btn');
deleteBtns.forEach(btn => {
btn.addEventListener('click', (e) => {
- const marketIndex = parseInt(e.target.dataset.marketIndex);
- this.deleteMarket(marketIndex);
+ const marketId = e.target.dataset.marketId;
+ this.deleteMarket(marketId);
});
});
}
@@ -517,8 +692,8 @@ class ZzimManager {
}
}
- // 마켓 찜하기 체크박스 토글
- async toggleMarketForZzim(marketIndex, isChecked) {
+ // 마켓 체크박스 토글 (통합)
+ async toggleMarketCheckbox(marketId, checkboxType, isChecked) {
try {
// 기존 마켓 목록 가져오기
const response = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${this.user_id}&select=my_markets`, {
@@ -536,17 +711,22 @@ class ZzimManager {
const data = await response.json();
const markets = data[0]?.my_markets || [];
- if (marketIndex < 0 || marketIndex >= markets.length) {
- this.showError('잘못된 마켓 인덱스입니다.');
+ // 마켓 ID로 해당 마켓 찾기
+ const market = markets.find(market => `${market.market_url}_${market.created_at}` === marketId);
+
+ if (!market) {
+ this.showError('잘못된 마켓 ID입니다.');
return;
}
- // 찜하기 대상 상태 업데이트
- markets[marketIndex] = {
- ...markets[marketIndex],
- for_zzim: isChecked,
- updated_at: new Date().toISOString()
- };
+ // 체크박스 타입에 따라 해당 필드 업데이트
+ if (checkboxType === 'for_zzim') {
+ market.for_zzim = isChecked;
+ } else if (checkboxType === 'for_mutual_zzim') {
+ market.for_mutual_zzim = isChecked;
+ }
+
+ market.updated_at = new Date().toISOString();
// user_markets 테이블 업데이트
const updateResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${this.user_id}`, {
@@ -562,17 +742,21 @@ class ZzimManager {
});
if (!updateResponse.ok) {
- throw new Error('마켓 찜하기 설정 변경 실패');
+ throw new Error('마켓 설정 변경 실패');
}
- this.showSuccess(`마켓이 ${isChecked ? '찜하기 대상에 포함' : '찜하기 대상에서 제외'}되었습니다.`);
+ const statusMessage = checkboxType === 'for_zzim'
+ ? (isChecked ? '내 찜하기 대상에 포함' : '내 찜하기 대상에서 제외')
+ : (isChecked ? '품앗이 대상에 포함' : '품앗이 대상에서 제외');
+
+ this.showSuccess(`마켓이 ${statusMessage}되었습니다.`);
} catch (error) {
- console.error('마켓 찜하기 설정 변경 오류:', error);
- this.showError('마켓 찜하기 설정 변경 중 오류가 발생했습니다.');
+ console.error('마켓 설정 변경 오류:', error);
+ this.showError('마켓 설정 변경 중 오류가 발생했습니다.');
// 오류 발생 시 체크박스 상태 원복
- const checkbox = document.getElementById(`market-check-${marketIndex}`);
+ const checkbox = document.querySelector(`[data-market-id="${marketId}"][data-checkbox-type="${checkboxType}"]`);
if (checkbox) {
checkbox.checked = !isChecked;
}
@@ -671,6 +855,7 @@ class ZzimManager {
market_nickname: marketNickname,
is_visible: true, // 다른 사람에게 노출 (기본값: 노출)
for_zzim: true, // 내가 찜하기 할 때 포함 (기본값: 포함)
+ for_mutual_zzim: true, // 품앗이 대상 여부 (기본값: 포함)
zzim_received_count: 0,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString()
@@ -751,7 +936,7 @@ class ZzimManager {
}
}
- async editMarket(marketIndex) {
+ async editMarket(marketId) {
try {
// 기존 마켓 목록 가져오기
const response = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${this.user_id}&select=my_markets`, {
@@ -769,15 +954,16 @@ class ZzimManager {
const data = await response.json();
const markets = data[0]?.my_markets || [];
- if (marketIndex < 0 || marketIndex >= markets.length) {
- this.showError('잘못된 마켓 인덱스입니다.');
+ // 마켓 ID로 해당 마켓 찾기
+ const market = markets.find(market => `${market.market_url}_${market.created_at}` === marketId);
+
+ if (!market) {
+ this.showError('잘못된 마켓 ID입니다.');
return;
}
- const market = markets[marketIndex];
-
// 모달에 기존 데이터 채우기
- this.currentEditIndex = marketIndex;
+ this.currentEditIndex = markets.indexOf(market);
this.openEditModal(market);
} catch (error) {
@@ -793,6 +979,7 @@ class ZzimManager {
const nameInput = document.getElementById('edit-market-name');
const nicknameInput = document.getElementById('edit-market-nickname');
const forZzimCheckbox = document.getElementById('edit-market-for-zzim');
+ const forMutualZzimCheckbox = document.getElementById('edit-market-for-mutual-zzim');
const visibleCheckbox = document.getElementById('edit-market-visible');
// 기존 데이터로 폼 채우기
@@ -800,6 +987,7 @@ class ZzimManager {
if (nameInput) nameInput.value = market.market_name || '';
if (nicknameInput) nicknameInput.value = market.market_nickname || '';
if (forZzimCheckbox) forZzimCheckbox.checked = market.for_zzim !== false;
+ if (forMutualZzimCheckbox) forMutualZzimCheckbox.checked = market.for_mutual_zzim !== false;
if (visibleCheckbox) visibleCheckbox.checked = market.is_visible !== false;
// 모달 표시
@@ -858,6 +1046,7 @@ class ZzimManager {
const nameInput = document.getElementById('edit-market-name');
const nicknameInput = document.getElementById('edit-market-nickname');
const forZzimCheckbox = document.getElementById('edit-market-for-zzim');
+ const forMutualZzimCheckbox = document.getElementById('edit-market-for-mutual-zzim');
const visibleCheckbox = document.getElementById('edit-market-visible');
const saveBtn = document.querySelector('.btn-modal-save');
@@ -865,6 +1054,7 @@ class ZzimManager {
const marketName = nameInput?.value.trim() || '';
const marketNickname = nicknameInput?.value.trim() || '';
const forZzim = forZzimCheckbox?.checked || false;
+ const forMutualZzim = forMutualZzimCheckbox?.checked || false;
const isVisible = visibleCheckbox?.checked || false;
// 유효성 검사
@@ -927,6 +1117,7 @@ class ZzimManager {
market_name: marketName,
market_nickname: marketNickname,
for_zzim: forZzim,
+ for_mutual_zzim: forMutualZzim,
is_visible: isVisible,
updated_at: new Date().toISOString()
};
@@ -966,7 +1157,7 @@ class ZzimManager {
}
}
- async toggleMarketVisibility(marketIndex) {
+ async toggleMarketVisibility(marketId) {
try {
// 기존 마켓 목록 가져오기
const response = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${this.user_id}&select=my_markets`, {
@@ -984,17 +1175,17 @@ class ZzimManager {
const data = await response.json();
const markets = data[0]?.my_markets || [];
- if (marketIndex < 0 || marketIndex >= markets.length) {
- this.showError('잘못된 마켓 인덱스입니다.');
- return;
- }
-
+ // 마켓 ID로 해당 마켓 찾기
+ const market = markets.find(market => `${market.market_url}_${market.created_at}` === marketId);
+
+ if (!market) {
+ this.showError('잘못된 마켓 ID입니다.');
+ return;
+ }
+
// 노출 상태 토글
- markets[marketIndex] = {
- ...markets[marketIndex],
- is_visible: !markets[marketIndex].is_visible,
- updated_at: new Date().toISOString()
- };
+ market.is_visible = !market.is_visible;
+ market.updated_at = new Date().toISOString();
// user_markets 테이블 업데이트
const updateResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${this.user_id}`, {
@@ -1014,7 +1205,7 @@ class ZzimManager {
}
await this.loadMyMarkets();
- this.showSuccess(`마켓이 ${markets[marketIndex].is_visible ? '노출' : '숨김'} 상태로 변경되었습니다.`);
+ this.showSuccess(`마켓이 ${market.is_visible ? '노출' : '숨김'} 상태로 변경되었습니다.`);
} catch (error) {
console.error('마켓 노출 설정 변경 오류:', error);
@@ -1022,7 +1213,7 @@ class ZzimManager {
}
}
- async deleteMarket(marketIndex) {
+ async deleteMarket(marketId) {
try {
// 기존 마켓 목록 가져오기
const response = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${this.user_id}&select=my_markets`, {
@@ -1040,19 +1231,20 @@ class ZzimManager {
const data = await response.json();
const markets = data[0]?.my_markets || [];
- if (marketIndex < 0 || marketIndex >= markets.length) {
- this.showError('잘못된 마켓 인덱스입니다.');
+ // 마켓 ID로 해당 마켓 찾기
+ const market = markets.find(market => `${market.market_url}_${market.created_at}` === marketId);
+
+ if (!market) {
+ this.showError('잘못된 마켓 ID입니다.');
return;
}
- const market = markets[marketIndex];
-
if (!confirm(`정말로 "${market.market_nickname}" 마켓을 삭제하시겠습니까?`)) {
return;
}
// 마켓 삭제 (배열에서 제거)
- markets.splice(marketIndex, 1);
+ markets.splice(markets.indexOf(market), 1);
// user_markets 테이블 업데이트
const updateResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${this.user_id}`, {
@@ -1409,8 +1601,25 @@ class ZzimManager {
// 마켓 URL에서 스토어 ID 추출
const storeId = market.market_url.split('/').pop();
+ // 올바른 네이버 스마트스토어 URL 생성
+ let finalTargetUrl = targetUrl;
+
+ // URL에 찜하기 파라미터 추가
+ const urlObj = new URL(finalTargetUrl);
+ urlObj.searchParams.set('auto_zzim', 'true');
+ urlObj.searchParams.set('max_zzim', '50');
+
+ // 네이버 스마트스토어는 cp 파라미터를 사용 (page가 아님)
+ if (!urlObj.searchParams.has('cp')) {
+ urlObj.searchParams.set('cp', '1'); // 첫 번째 페이지부터 시작
+ }
+
+ finalTargetUrl = urlObj.toString();
+
+ console.log('[ZzimManager] 최종 찜하기 URL:', finalTargetUrl);
+
// 로그인 리다이렉트 URL 생성
- const loginRedirectUrl = `https://nid.naver.com/nidlogin.login?url=${encodeURIComponent(targetUrl + (targetUrl.includes('?') ? '&' : '?') + 'auto_zzim=true&max_zzim=50')}`;
+ const loginRedirectUrl = `https://nid.naver.com/nidlogin.login?url=${encodeURIComponent(finalTargetUrl)}`;
this.showSuccess(`찜하기 페이지로 이동합니다. (${market.market_nickname})`);
@@ -1448,25 +1657,23 @@ class ZzimManager {
async updateZzimStats(count, zzimType, targetMarket = null) {
try {
- // 1. 찜을 해준 사용자의 마일리지 증가
- const mileageIncrease = zzimType === 'mutual' ? count * 2 : count; // 품앗이는 마일리지 2배
+ console.log('찜 통계 업데이트 시작:', { count, zzimType, targetMarket });
- await fetch(`${this.SUPABASE_URL}/rest/v1/users?id=eq.${this.user_id}`, {
- method: 'PATCH',
- headers: {
- 'Authorization': `Bearer ${this.access_token}`,
- 'apikey': this.SUPABASE_ANON_KEY,
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- zzim_mile: `zzim_mile + ${mileageIncrease}`
- })
- });
+ // 현재 제한 정보 확인
+ if (!this.currentLimits) {
+ console.warn('제한 정보가 없음, 통계 다시 로드');
+ await this.loadZzimStats();
+ }
- // 2. 찜을 받은 마켓의 찜받은 개수 증가 (품앗이인 경우)
- if (zzimType === 'mutual' && targetMarket && targetMarket.owner_user_id) {
- // 찜을 받은 사용자의 my_zzim 증가
- await fetch(`${this.SUPABASE_URL}/rest/v1/users?id=eq.${targetMarket.owner_user_id}`, {
+ const limits = this.currentLimits || { mileage_per_zzim: 1 };
+ const today = new Date().toISOString().split('T')[0];
+
+ if (zzimType === 'my_market') {
+ // 내 마켓 찜하기: 오늘 찜한 개수 증가 + 받은 찜 개수 증가
+ console.log('내 마켓 찜하기 통계 업데이트');
+
+ // users 테이블 업데이트
+ const myMarketUpdateResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/users?id=eq.${this.user_id}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${this.access_token}`,
@@ -1474,37 +1681,53 @@ class ZzimManager {
'Content-Type': 'application/json'
},
body: JSON.stringify({
+ today_zzim_count: `today_zzim_count + ${count}`,
+ today_zzim_date: today,
my_zzim: `my_zzim + ${count}`
})
});
- // 해당 마켓의 찜받은 개수 증가
- const ownerMarketsResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${targetMarket.owner_user_id}&select=my_markets`, {
+ if (!myMarketUpdateResponse.ok) {
+ throw new Error('내 마켓 찜하기 통계 업데이트 실패');
+ }
+
+ // user_markets 테이블의 집계 필드는 제거되었으므로 별도 업데이트 필요 없음
+
+ // 내 마켓의 찜받은 개수도 증가
+ if (targetMarket) {
+ await this.updateMarketZzimCount(targetMarket.market_url, count);
+ }
+
+ // 찜 기록 저장
+ await this.saveZzimRecord(zzimType, targetMarket, count, 0);
+
+ } else if (zzimType === 'mutual') {
+ // 품앗이 찜하기: 내 마일리지 차감 + 상대방 마일리지 증가 + 상대방 받은 찜 개수 증가
+ console.log('품앗이 찜하기 통계 업데이트');
+
+ const mileageUsed = count * limits.mileage_per_zzim;
+
+ // 내 마일리지 차감 (users 테이블)
+ const myMileageUpdateResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/users?id=eq.${this.user_id}`, {
+ method: 'PATCH',
headers: {
'Authorization': `Bearer ${this.access_token}`,
'apikey': this.SUPABASE_ANON_KEY,
'Content-Type': 'application/json'
- }
+ },
+ body: JSON.stringify({
+ available_zzim_mile: `available_zzim_mile - ${mileageUsed}`
+ })
});
- if (ownerMarketsResponse.ok) {
- const ownerData = await ownerMarketsResponse.json();
- const ownerMarkets = ownerData[0]?.my_markets || [];
-
- // 해당 마켓 찾아서 찜받은 개수 증가
- const updatedOwnerMarkets = ownerMarkets.map(market => {
- if (market.market_url === targetMarket.market_url) {
- return {
- ...market,
- zzim_received_count: (market.zzim_received_count || 0) + count,
- updated_at: new Date().toISOString()
- };
- }
- return market;
- });
-
- // 업데이트된 마켓 목록 저장
- await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${targetMarket.owner_user_id}`, {
+ if (!myMileageUpdateResponse.ok) {
+ throw new Error('내 마일리지 차감 실패');
+ }
+
+ // 상대방 마일리지 증가 및 받은 찜 개수 증가
+ if (targetMarket && targetMarket.owner_user_id) {
+ // 상대방 users 테이블 업데이트
+ const targetUpdateResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/users?id=eq.${targetMarket.owner_user_id}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${this.access_token}`,
@@ -1512,15 +1735,88 @@ class ZzimManager {
'Content-Type': 'application/json'
},
body: JSON.stringify({
- my_markets: updatedOwnerMarkets
+ zzim_mile: `zzim_mile + ${mileageUsed}`,
+ available_zzim_mile: `available_zzim_mile + ${mileageUsed}`,
+ my_zzim: `my_zzim + ${count}`
})
});
+
+ if (!targetUpdateResponse.ok) {
+ console.warn('상대방 마일리지 및 받은 찜 개수 업데이트 실패');
+ }
+
+ // (중복 패치 제거: targetUpdateResponse 에서 이미 users 테이블을 갱신했습니다.)
+ // 상대방 users 테이블도 업데이트 (호환성 유지)
+ const targetUsersUpdateResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/users?id=eq.${targetMarket.owner_user_id}`, {
+ method: 'PATCH',
+ headers: {
+ 'Authorization': `Bearer ${this.access_token}`,
+ 'apikey': this.SUPABASE_ANON_KEY,
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ zzim_mile: `zzim_mile + ${mileageUsed}`,
+ available_zzim_mile: `available_zzim_mile + ${mileageUsed}`,
+ my_zzim: `my_zzim + ${count}`
+ })
+ });
+
+ if (!targetUsersUpdateResponse.ok) {
+ console.warn('상대방 users 테이블 업데이트 실패');
+ }
+
+ // 상대방 마켓의 찜받은 개수도 증가
+ await this.updateMarketZzimCount(targetMarket.market_url, count, targetMarket.owner_user_id);
}
+
+ // 찜 기록 저장
+ await this.saveZzimRecord(zzimType, targetMarket, count, -mileageUsed);
+
+ console.log(`품앗이 완료: 마일리지 ${mileageUsed} 사용, 찜 ${count}개 제공`);
}
- // 3. 내 마켓 찜하기인 경우 내 찜받은 개수 증가
- if (zzimType === 'my_market') {
- await fetch(`${this.SUPABASE_URL}/rest/v1/users?id=eq.${this.user_id}`, {
+ // 통계 다시 로드하여 UI 업데이트
+ await this.loadZzimStats();
+
+ console.log('찜 통계 업데이트 완료');
+
+ } catch (error) {
+ console.error('찜 통계 업데이트 오류:', error);
+ throw error;
+ }
+ }
+
+ // 마켓별 찜받은 개수 업데이트
+ async updateMarketZzimCount(marketUrl, count, userId = null) {
+ try {
+ const targetUserId = userId || this.user_id;
+
+ const marketsResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${targetUserId}&select=my_markets`, {
+ headers: {
+ 'Authorization': `Bearer ${this.access_token}`,
+ 'apikey': this.SUPABASE_ANON_KEY,
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ if (marketsResponse.ok) {
+ const marketsData = await marketsResponse.json();
+ const markets = marketsData[0]?.my_markets || [];
+
+ // 해당 마켓 찾아서 찜받은 개수 증가
+ const updatedMarkets = markets.map(market => {
+ if (market.market_url === marketUrl) {
+ return {
+ ...market,
+ zzim_received_count: (market.zzim_received_count || 0) + count,
+ updated_at: new Date().toISOString()
+ };
+ }
+ return market;
+ });
+
+ // 업데이트된 마켓 목록 저장
+ await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${targetUserId}`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${this.access_token}`,
@@ -1528,53 +1824,88 @@ class ZzimManager {
'Content-Type': 'application/json'
},
body: JSON.stringify({
- my_zzim: `my_zzim + ${count}`
+ my_markets: updatedMarkets
})
});
- // 내 마켓의 찜받은 개수도 증가
- const myMarketsResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${this.user_id}&select=my_markets`, {
- headers: {
- 'Authorization': `Bearer ${this.access_token}`,
- 'apikey': this.SUPABASE_ANON_KEY,
- 'Content-Type': 'application/json'
- }
- });
-
- if (myMarketsResponse.ok) {
- const myData = await myMarketsResponse.json();
- const myMarkets = myData[0]?.my_markets || [];
-
- // 해당 마켓의 찜받은 개수 증가
- const updatedMyMarkets = myMarkets.map(market => {
- if (market.market_url === targetMarket?.market_url) {
- return {
- ...market,
- zzim_received_count: (market.zzim_received_count || 0) + count,
- updated_at: new Date().toISOString()
- };
- }
- return market;
- });
-
- // 업데이트된 마켓 목록 저장
- await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=eq.${this.user_id}`, {
- method: 'PATCH',
+ console.log(`마켓 ${marketUrl} 찜받은 개수 ${count} 증가`);
+ }
+ } catch (error) {
+ console.error('마켓 찜받은 개수 업데이트 오류:', error);
+ }
+ }
+
+ // 찜 기록 저장
+ async saveZzimRecord(zzimType, targetMarket, zzimCount, mileageEarned) {
+ try {
+ const record = {
+ user_id: this.user_id,
+ market_url: targetMarket?.market_url || '',
+ market_name: targetMarket?.market_name || '',
+ market_nickname: targetMarket?.market_nickname || '',
+ zzim_type: zzimType,
+ zzim_count: zzimCount,
+ mileage_earned: mileageEarned,
+ target_user_id: targetMarket?.owner_user_id || null,
+ created_at: new Date().toISOString()
+ };
+
+ const response = await fetch(`${this.SUPABASE_URL}/rest/v1/jjim`, {
+ method: 'POST',
headers: {
'Authorization': `Bearer ${this.access_token}`,
'apikey': this.SUPABASE_ANON_KEY,
'Content-Type': 'application/json'
},
- body: JSON.stringify({
- my_markets: updatedMyMarkets
- })
+ body: JSON.stringify(record)
});
- }
+
+ if (!response.ok) {
+ console.warn('찜 기록 저장 실패:', response.status);
+ } else {
+ console.log('찜 기록 저장 완료');
+ }
+ } catch (error) {
+ console.error('찜 기록 저장 오류:', error);
+ }
+ }
+
+ // 찜하기 가능 여부 확인
+ canZzim(zzimType) {
+ if (!this.currentStats || !this.currentLimits) {
+ return { canZzim: false, reason: '통계 정보를 불러오는 중입니다.' };
+ }
+
+ if (zzimType === 'my_market') {
+ // 내 마켓 찜하기: 오늘 찜한 개수 확인
+ const todayCount = this.currentStats.todayZzimCount;
+ const dailyLimit = this.currentLimits.daily_zzim_limit;
+
+ if (todayCount >= dailyLimit) {
+ return {
+ canZzim: false,
+ reason: `오늘 찜 제한에 도달했습니다. (${todayCount}/${dailyLimit})`
+ };
}
- } catch (error) {
- console.error('찜 통계 업데이트 오류:', error);
+ return { canZzim: true, remaining: dailyLimit - todayCount };
+
+ } else if (zzimType === 'mutual') {
+ // 품앗이 찜하기: 사용 가능한 마일리지 확인
+ const availableMileage = this.currentStats.availableZzimMile;
+ const requiredMileage = 50; // 마켓당 50개 찜 가정
+
+ if (availableMileage < requiredMileage) {
+ return {
+ canZzim: false,
+ reason: `품앗이에 필요한 마일리지가 부족합니다. (보유: ${availableMileage}, 필요: ${requiredMileage})`
+ };
+ }
+
+ return { canZzim: true, remaining: Math.floor(availableMileage / requiredMileage) };
}
+
+ return { canZzim: false, reason: '알 수 없는 찜 타입입니다.' };
}
async getActiveMarkets() {
@@ -1606,8 +1937,31 @@ class ZzimManager {
async getMutualMarkets() {
try {
- // 다른 사용자들의 노출된 마켓 목록 가져오기 (품앗이용)
- const response = await fetch(`${this.SUPABASE_URL}/rest/v1/user_markets?user_id=neq.${this.user_id}&select=my_markets,user_id&limit=50`, {
+ console.log('[품앗이] 품앗이 마켓 목록 조회 시작');
+
+ // 내 현재 마일리지 확인 (users 테이블)
+ const myStatsResponse = await fetch(`${this.SUPABASE_URL}/rest/v1/users?id=eq.${this.user_id}&select=available_zzim_mile`, {
+ headers: {
+ 'Authorization': `Bearer ${this.access_token}`,
+ 'apikey': this.SUPABASE_ANON_KEY,
+ 'Content-Type': 'application/json'
+ }
+ });
+
+ let myAvailableMileage = 0;
+ if (myStatsResponse.ok) {
+ const myData = await myStatsResponse.json();
+ myAvailableMileage = myData[0]?.available_zzim_mile || 0;
+ }
+
+ console.log('[품앗이] 내 사용 가능한 마일리지:', myAvailableMileage);
+
+ if (myAvailableMileage <= 0) {
+ throw new Error('사용 가능한 마일리지가 없습니다. 먼저 다른 사람의 마켓에 찜을 받아 마일리지를 적립하세요.');
+ }
+
+ // 다른 사용자들의 노출된 마켓 목록 가져오기 (품앗이용) - v_user_market_stats 뷰 사용
+ const response = await fetch(`${this.SUPABASE_URL}/rest/v1/v_user_market_stats?user_id=neq.${this.user_id}&available_zzim_mile=gt.0&select=user_id,available_zzim_mile,my_markets&limit=100`, {
headers: {
'Authorization': `Bearer ${this.access_token}`,
'apikey': this.SUPABASE_ANON_KEY,
@@ -1620,25 +1974,56 @@ class ZzimManager {
}
const data = await response.json();
+ console.log('[품앗이] 조회된 사용자 데이터:', data.length);
+
const mutualMarkets = [];
// 각 사용자의 노출된 마켓들을 수집
data.forEach(userMarket => {
const markets = userMarket.my_markets || [];
- const visibleMarkets = markets.filter(market => market.is_visible !== false);
+ const userMileage = userMarket.available_zzim_mile || 0;
- // 사용자 정보를 마켓에 추가
- visibleMarkets.forEach(market => {
- mutualMarkets.push({
- ...market,
- owner_user_id: userMarket.user_id
+ // 마일리지가 있는 사용자의 노출된 마켓만 수집
+ if (userMileage > 0) {
+ const visibleMarkets = markets.filter(market =>
+ market.is_visible !== false &&
+ market.for_mutual_zzim !== false // 품앗이 대상으로 설정된 마켓만
+ );
+
+ // 사용자 정보를 마켓에 추가
+ visibleMarkets.forEach(market => {
+ mutualMarkets.push({
+ ...market,
+ owner_user_id: userMarket.user_id,
+ owner_available_mileage: userMileage
+ });
});
- });
+ }
});
- // 랜덤하게 섞고 최대 10개만 반환
- const shuffled = mutualMarkets.sort(() => 0.5 - Math.random());
- return shuffled.slice(0, 10);
+ console.log('[품앗이] 수집된 품앗이 마켓 수:', mutualMarkets.length);
+
+ if (mutualMarkets.length === 0) {
+ throw new Error('현재 품앗이 가능한 마켓이 없습니다.');
+ }
+
+ // 우선순위 기반 정렬 (마일리지가 많은 사용자 우선)
+ mutualMarkets.sort((a, b) => {
+ // 1차: 마일리지 많은 순
+ if (b.owner_available_mileage !== a.owner_available_mileage) {
+ return b.owner_available_mileage - a.owner_available_mileage;
+ }
+ // 2차: 최신 등록 순
+ return new Date(b.created_at || 0) - new Date(a.created_at || 0);
+ });
+
+ // 내 마일리지로 처리 가능한 개수만큼 반환 (최대 10개)
+ const maxMarkets = Math.min(10, Math.floor(myAvailableMileage / 50)); // 마켓당 50개 찜 가정
+ const selectedMarkets = mutualMarkets.slice(0, maxMarkets);
+
+ console.log('[품앗이] 선택된 품앗이 마켓:', selectedMarkets.length);
+
+ return selectedMarkets;
} catch (error) {
console.error('품앗이 마켓 목록 조회 오류:', error);