From a9ca5fbcf9f11d1281e80f3c2a6ffbd810d834bb Mon Sep 17 00:00:00 2001
From: Layne <laynebalsters@gmail.com>
Date: Tue, 29 Jun 2021 09:15:31 -0400
Subject: [PATCH 1/4] wired custom ui boxes

---
 .../images/wired/card-action-corners.png      | Bin 0 -> 1827 bytes
 src/views/wired/WiredView.scss                | 122 ++++++++++++++++++
 src/views/wired/views/base/WiredBaseView.tsx  |  15 ++-
 3 files changed, 131 insertions(+), 6 deletions(-)
 create mode 100644 src/assets/images/wired/card-action-corners.png

diff --git a/src/assets/images/wired/card-action-corners.png b/src/assets/images/wired/card-action-corners.png
new file mode 100644
index 0000000000000000000000000000000000000000..faec2349dc752a8e3ab656e8470bd5ab3bdd548c
GIT binary patch
literal 1827
zcmcIlPl()97>|ghwpJ=46%P_p!L9lxe<uH4?6l0zY~2B~uDfI176o5kUS`53c`?cC
z%q|K=7Q{mjiWj9Gym}C!;-M;nH*ey_vpu*+^(ct=z4_NF+hr~WlDs6p_xpa|@B8xJ
zd+Td2oI3Hu2}zPpbynLOaDPag$B)7F^5C@txILJ!UMVH%<fG!ePx|=A<C1hNiMw0X
zmj9whd0HbO4_IxK=75%@^A|@sq1&vI1J;YPhVt9j-zjn&Hk4N_U-R=8>&L5m1>4+P
z>(ae#ibLh%1^N8Q1A>%QL>{F{R(hj`GUoMQEMBXMJcd-;4W%gp%3J=r+~Nh3t(uLf
zZo0CAYr1V}b^AHl&~&V7uBz9OrhA(0S&lqC6o^)Yk+;#lG>rvM4W(aIxu>eb;jlKW
z*LcxWb&P?-Pz?hC0+qX2MMfwq&(0XytfWPpS253I!AJr=s2U0=ourWFbK0z&+60EF
zBa*9nO%o~2fWCh;G)?E|vRc`JC{w+M5|`cGoT(eE<b#5;l^vE<XJ^6kKCgJ$=l9Sy
z|NJk7A)N=z2SqZrC!{J%SPI-FVD+)S+-nt#RJ`bNp3DlhK8q+DkhQ$z6B=hi!#Sa8
zI)$}K#TtsC89LHzWZ<smdY0~42GUGV(<V?KIw2$#Sq#j>INDtV>ib?ND=U&w)@e5s
z5LJug&@)|PGM!>%Vw1wfVkmG3MV1@kFmfUbo8ed&%x`l#5MGG+lg14>1&+C&9;=%s
zqmUbM%mBHXsUcTqAqw0&wQ!(EIKnfwmx>tv9g^J5DpZBQ=ui#U%`iZYfg@zvc7Os)
zbCE+_TBn%Uj^QZsowzNY@WSUIxLa4`ka`g>QUV<mr=-W!JnM;m26o6|H7=oeyVE~p
zlf5||C9yniJC9J&?G1&BGBe12@;W}my~T7+<`4S}NRKG~1Xl8>8j^xFd*Ji}?WNvJ
zeo1zY7Qa~O|5x!-YiXZkJqF9Cs)%${vCvEkqyD#McWOTCn<jL$sAxGgVwv>jmRvZz
zO(`*K!!=E$8Q4KVWMUNP1S1kT77HSa={T6ENaC5E39Wi`{IT-8mdx2?Sck=Mz5&3)
zd<$V2BwoM<v3z~dht1{nPP^G%djFG+=EK*d<G0yc-#`6lerx|`@$B<CxpsU1De1>E
zH?A%zAAa<}N$<=fzrMUrS_fB8KN)m>|EzWT(jVb7E!Fzv^55^0Z-2UF{_yk7558HG
juYB=o`Pi3lU%&sW+F!419-NEBHr82LYk$7{#ykH20l7o+

literal 0
HcmV?d00001

diff --git a/src/views/wired/WiredView.scss b/src/views/wired/WiredView.scss
index bab60efb..ce1bc799 100644
--- a/src/views/wired/WiredView.scss
+++ b/src/views/wired/WiredView.scss
@@ -1,5 +1,6 @@
 .nitro-wired {
     width: 300px;
+	padding:7px;
 
     .icon {
 		width: 16px;
@@ -35,4 +36,125 @@
 			background-image: url('../../assets/images/wired/icon_wired_rotate_counter_clockwise.png');
 		}
 	}
+
+	.nitro-wired-header {
+		color: #000;
+		margin-bottom:3px;
+
+		.nitro-wired-title, .nitro-wired-close {
+			border:1px solid rgba($black,.8);
+			background-image: linear-gradient(45deg, #00d9cb 25%, #00bdb0 25%, #00bdb0 50%, #00d9cb 50%, #00d9cb 75%, #00bdb0 75%, #00bdb0 100%);
+			background-size: 197.99px 197.99px;
+			animation: wiredSlider 3s linear infinite;
+			text-align: center;
+			box-shadow:inset 0 0 0 2px rgba($white,.6), 0 2px rgba($black,.4);
+		}
+
+		.nitro-wired-title {
+			margin-right:3px;
+		}
+
+		.nitro-wired-close {
+			min-width: 23px;
+		}
+	}
+
+	&.nitro-wired-trigger {
+		background-color: #3b2516 !important;
+		border: 1px solid #000 !important;
+		box-shadow: inset 0px -2px #50321f,
+					inset 0px -3px #86583b,
+					inset 0 0 0 1px #86583b,
+					inset 0 0 0 3px #644029,
+					inset 0 0 0 4px rgba($black,.4) !important;
+
+		.bg-light,.bg-primary {
+			background-color: transparent !important;
+		}
+
+		.bg-dark {
+			background-color: #000 !important;
+		}
+	}
+
+	&.nitro-wired-action {
+		background-color: #686868 !important;
+		border: 1px solid #000 !important;
+		box-shadow: inset 0px -2px #9d9d9d,
+					inset 0px -3px #c5c5c5,
+					inset 0 0 0 1px #c5c5c5,
+					inset 0 0 0 3px #9d9d9d,
+					inset 0 0 0 4px rgba($black,.4) !important;
+
+		.bg-light,.bg-primary {
+			background-color: transparent !important;
+		}
+
+		.bg-dark {
+			background-color: #000 !important;
+		}
+
+		&::before,
+		&::after,
+		.content-area::before,
+		.content-area::after {
+			content: '';
+			height: 6px;
+			width: 6px;
+			position: absolute;
+			background-image: url('../../assets/images/wired/card-action-corners.png');
+		}
+
+		&::before {
+			background-position: 0 0;
+			top: 0;
+			left: 0;
+		}
+
+		&::after {
+			background-position: 6px 0;
+			top: 0;
+			right: 0;
+		}
+
+		.content-area {
+			&::before {
+				background-position: 0 6px;
+				bottom: 0;
+				left: 0;
+			}
+	
+			&::after {
+				background-position: 6px 6px;
+				bottom: 0;
+				right: 0;
+			}
+		}
+	}
+
+	&.nitro-wired-condition {
+		background-color: #cfd2dd !important;
+		border: 1px solid #000 !important;
+		box-shadow: inset 0 0 0 3px #efefef, inset 4px 4px #abaeb9 !important;
+		color: #000;
+
+		.bg-light,.bg-primary {
+			background-color: transparent !important;
+		}
+
+		.bg-dark {
+			background-color: #000 !important;
+		}
+	}
+}
+
+
+@keyframes wiredSlider {
+	0% {
+		background-position: 0 0;
+	}
+	
+	100% {
+		background-position: 0 -197.99px;
+	}
 }
diff --git a/src/views/wired/views/base/WiredBaseView.tsx b/src/views/wired/views/base/WiredBaseView.tsx
index 3bbc1c85..44fc0106 100644
--- a/src/views/wired/views/base/WiredBaseView.tsx
+++ b/src/views/wired/views/base/WiredBaseView.tsx
@@ -2,7 +2,7 @@ import { FC, useCallback, useEffect, useState } from 'react';
 import { GetSessionDataManager } from '../../../../api';
 import { WiredEvent } from '../../../../events';
 import { dispatchUiEvent } from '../../../../hooks/events';
-import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../../../layout';
+import { NitroCardContentView, NitroCardView } from '../../../../layout';
 import { LocalizeText } from '../../../../utils/LocalizeText';
 import { useWiredContext } from '../../context/WiredContext';
 import { WiredFurniType } from '../../WiredView.types';
@@ -52,9 +52,12 @@ export const WiredBaseView: FC<WiredBaseViewProps> = props =>
     }, [ setTrigger ]);
 
     return (
-        <NitroCardView className="nitro-wired" simple={ true }>
-            <NitroCardHeaderView headerText={ LocalizeText('wiredfurni.title') } onCloseClick={ close } />
-            <NitroCardContentView className="text-black">
+        <NitroCardView className={`nitro-wired nitro-wired-${wiredType} ` + (wiredType == 'trigger' ? 'rounded-0' : 'rounded-2')}>
+            <div className="nitro-wired-header d-flex">
+                <div className="nitro-wired-title rounded-start w-100 drag-handler">{LocalizeText('wiredfurni.title')}</div>
+                <div className="nitro-wired-close rounded-end flex-shrink-0" onClick={ close }><i className="fas fa-times" /></div>
+            </div>
+            <NitroCardContentView>
                 <div className="d-flex align-items-center">
                     <i className={ `me-2 icon icon-wired-${ wiredType }` } />
                     <div className="fw-bold">{ wiredName }</div>
@@ -73,8 +76,8 @@ export const WiredBaseView: FC<WiredBaseViewProps> = props =>
                         <div>{ LocalizeText('wiredfurni.pickfurnis.desc') }</div>
                     </> }
                 <div className="d-flex mt-3">
-                    <button className="btn btn-success me-2 w-100" onClick={ onSave }>{ LocalizeText('wiredfurni.ready') }</button>
-                    <button className="btn btn-secondary w-100" onClick={ close }>{ LocalizeText('cancel') }</button>
+                    <button className="btn btn-sm btn-success me-2 w-100" onClick={ onSave }>{ LocalizeText('wiredfurni.ready') }</button>
+                    <button className="btn btn-sm btn-secondary w-100" onClick={ close }>{ LocalizeText('cancel') }</button>
                 </div>
             </NitroCardContentView>
         </NitroCardView>

From 6de6540a03682fe8008afc759e37eb9be16e8130 Mon Sep 17 00:00:00 2001
From: MyNameIsBatman <montevechiol@gmail.com>
Date: Tue, 29 Jun 2021 17:38:03 -0300
Subject: [PATCH 2/4] Give Reward Action

---
 .../wired/common/GetWiredActionLayout.tsx     |   3 +
 .../WiredActionBotGiveHandItemView.tsx        |   2 +-
 .../give-reward/WiredActionGiveRewardView.tsx | 173 ++++++++++++++++++
 .../WiredConditionActorHasHandItem.tsx        |   2 +-
 4 files changed, 178 insertions(+), 2 deletions(-)
 create mode 100644 src/views/wired/views/actions/give-reward/WiredActionGiveRewardView.tsx

diff --git a/src/views/wired/common/GetWiredActionLayout.tsx b/src/views/wired/common/GetWiredActionLayout.tsx
index fe1ca34f..9c698937 100644
--- a/src/views/wired/common/GetWiredActionLayout.tsx
+++ b/src/views/wired/common/GetWiredActionLayout.tsx
@@ -9,6 +9,7 @@ import { WiredActionCallAnotherStackView } from '../views/actions/call-another-s
 import { WiredActionChaseView } from '../views/actions/chase/WiredActionChaseView';
 import { WiredActionChatView } from '../views/actions/chat/WiredActionChatView';
 import { WiredActionFleeView } from '../views/actions/flee/WiredActionFleeView';
+import { WiredActionGiveRewardView } from '../views/actions/give-reward/WiredActionGiveRewardView';
 import { WiredActionGiveScoreToPredefinedTeamView } from '../views/actions/give-score-to-predefined-team/WiredActionGiveScoreToPredefinedTeamView';
 import { WiredActionGiveScoreView } from '../views/actions/give-score/WiredActionGiveScoreView';
 import { WiredActionJoinTeamView } from '../views/actions/join-team/WiredActionJoinTeamView';
@@ -50,6 +51,8 @@ export function GetWiredActionLayout(code: number): JSX.Element
             return <WiredActionChatView />;
         case WiredActionLayout.FLEE:
             return <WiredActionFleeView />;
+        case WiredActionLayout.GIVE_REWARD:
+            return <WiredActionGiveRewardView />;
         case WiredActionLayout.GIVE_SCORE:
             return <WiredActionGiveScoreView />;
         case WiredActionLayout.GIVE_SCORE_TO_PREDEFINED_TEAM:
diff --git a/src/views/wired/views/actions/bot-give-hand-item/WiredActionBotGiveHandItemView.tsx b/src/views/wired/views/actions/bot-give-hand-item/WiredActionBotGiveHandItemView.tsx
index 75c0db17..2b3f8d6f 100644
--- a/src/views/wired/views/actions/bot-give-hand-item/WiredActionBotGiveHandItemView.tsx
+++ b/src/views/wired/views/actions/bot-give-hand-item/WiredActionBotGiveHandItemView.tsx
@@ -31,7 +31,7 @@ export const WiredActionBotGiveHandItemView: FC<{}> = props =>
                 <input type="text" className="form-control form-control-sm" maxLength={ 32 } value={ botName } onChange={ event => setBotName(event.target.value) } />
             </div>
             <div className="fw-bold">{ LocalizeText('wiredfurni.params.handitem') }</div>
-            <select className="form-select" value={ handItemId } onChange={ (e) => setHandItemId(Number(e.target.value)) }>
+            <select className="form-select form-select-sm" value={ handItemId } onChange={ (e) => setHandItemId(Number(e.target.value)) }>
                 <option value="0">------</option>
                 {allowedHanditemIds && allowedHanditemIds.map(value =>
                     {
diff --git a/src/views/wired/views/actions/give-reward/WiredActionGiveRewardView.tsx b/src/views/wired/views/actions/give-reward/WiredActionGiveRewardView.tsx
new file mode 100644
index 00000000..0d857a67
--- /dev/null
+++ b/src/views/wired/views/actions/give-reward/WiredActionGiveRewardView.tsx
@@ -0,0 +1,173 @@
+import Slider from 'rc-slider/lib/Slider';
+import { FC, useCallback, useEffect, useState } from 'react';
+import { LocalizeText } from '../../../../../utils/LocalizeText';
+import { useWiredContext } from '../../../context/WiredContext';
+import { WiredFurniType } from '../../../WiredView.types';
+import { WiredActionBaseView } from '../base/WiredActionBaseView';
+
+export const WiredActionGiveRewardView: FC<{}> = props =>
+{
+    const [ limitEnabled, setLimitEnabled ] = useState(false);
+    const [ rewardTime, setRewardTime ] = useState(1);
+    const [ uniqueRewards, setUniqueRewards ] = useState(false);
+    const [ rewardsLimit, setRewardsLimit ] = useState(1);
+    const [ limitationInterval, setLimitationInterval ] = useState(1);
+    const [ rewards, setRewards ] = useState<{ isBadge: boolean, itemCode: string, probability: number }[]>([]);
+
+    const { trigger = null, setIntParams = null, setStringParam = null } = useWiredContext();
+
+    useEffect(() =>
+    {
+        setRewardTime(trigger.intData.length > 0 ? trigger.intData[0] : 0);
+        setUniqueRewards(trigger.intData.length > 1 ? trigger.intData[1] === 1 : false);
+        setRewardsLimit(trigger.intData.length > 2 ? trigger.intData[2] : 0);
+        setLimitationInterval(trigger.intData.length > 3 ? trigger.intData[3] : 0);
+        setLimitEnabled(trigger.intData.length > 3 ? trigger.intData[3] > 0 : false);
+
+        const readRewards: { isBadge: boolean, itemCode: string, probability: number }[] = [];
+
+        if(trigger.stringData.length > 0 && trigger.stringData.includes(';'))
+        {
+            const splittedRewards = trigger.stringData.split(';');
+
+            for(const rawReward of splittedRewards)
+            {
+                const reward = rawReward.split(',');
+
+                if(reward.length !== 3) continue;
+
+                readRewards.push({ isBadge: reward[0] === '0', itemCode: reward[1], probability: Number(reward[2]) });
+            }
+        }
+
+        if(readRewards.length === 0)
+        {
+            readRewards.push({ isBadge: false, itemCode: '', probability: null });
+        }
+
+        setRewards(readRewards);
+    }, [ trigger ]);
+
+    const addReward = useCallback(() =>
+    {
+        setRewards(rewards => [...rewards, { isBadge: false, itemCode: '', probability: null }]);
+    }, [ setRewards ]);
+
+    const removeReward = useCallback((index: number) =>
+    {
+        const rewardsClone = Array.from(rewards);
+        rewardsClone.splice(index, 1);
+
+        setRewards(rewardsClone);
+    }, [ rewards, setRewards ]);
+
+    const updateReward = useCallback((index: number, isBadge: boolean, itemCode: string, probability: number) =>
+    {
+        const rewardsClone = Array.from(rewards);
+        const reward = rewardsClone[index];
+
+        if(!reward) return;
+
+        reward.isBadge = isBadge;
+        reward.itemCode = itemCode;
+        reward.probability = probability;
+
+        setRewards(rewardsClone);
+    }, [ rewards, setRewards ]);
+
+    const save = useCallback(() =>
+    {       
+        let stringRewards = [];
+
+        for(const reward of rewards)
+        {
+            if(!reward.itemCode) continue;
+
+            const rewardsString = [reward.isBadge ? '0' : '1', reward.itemCode, reward.probability.toString()];
+            stringRewards.push(rewardsString.join(','));
+        }
+
+        if(stringRewards.length > 0)
+        {
+            setStringParam(stringRewards.join(';'));
+            setIntParams([rewardTime, uniqueRewards ? 1 : 0, rewardsLimit, limitationInterval]);
+        }
+    }, [ rewardTime, uniqueRewards, rewardsLimit, limitationInterval, rewards, setIntParams, setStringParam ]);
+
+    return (
+        <WiredActionBaseView requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ save }>
+            <div className="form-check">
+                <input className="form-check-input" type="checkbox" id="limitEnabled" onChange={(e) => setLimitEnabled(e.target.checked)} />
+                <label className="form-check-label" htmlFor="uniqueRewards">
+                    { LocalizeText('wiredfurni.params.prizelimit', ['amount'], [limitEnabled ? rewardsLimit.toString() : '']) }
+                </label>
+            </div>
+            { !limitEnabled && <div className="bg-muted rounded small text-black p-1 text-center">
+                    Reward limit not set. Make sure rewards are badges or non-tradeable items.
+                </div> }
+            { limitEnabled && <Slider 
+                defaultValue={ rewardsLimit }
+                dots={ true }
+                min={ 1 }
+                max={ 1000 }
+                step={ 1 }
+                onChange={ event => setRewardsLimit(event) }
+                /> }
+            <hr className="my-1 mb-2 bg-dark" />
+            <div className="fw-bold">How ofter can a user be rewarded?</div>
+            <div className="d-flex">
+                <select className="form-select form-select-sm w-100" value={ rewardTime } onChange={ (e) => setRewardTime(Number(e.target.value)) }>
+                    <option value="0">Once</option>
+                    <option value="3">Once every { limitationInterval } minutes</option>
+                    <option value="2">Once every { limitationInterval } hours</option>
+                    <option value="1">Once every { limitationInterval } days</option>
+                </select>
+                { rewardTime > 0 && <input type="number" className="ms-2 form-control form-control-sm" value={ limitationInterval } onChange={ event => setLimitationInterval(Number(event.target.value)) } /> }
+            </div>
+            <hr className="my-1 mb-2 bg-dark" />
+            <div className="form-check">
+                <input className="form-check-input" type="checkbox" id="uniqueRewards" checked={ uniqueRewards } onChange={(e) => setUniqueRewards(e.target.checked)} />
+                <label className="form-check-label" htmlFor="uniqueRewards">
+                    Unique rewards
+                </label>
+            </div>
+            <div className="bg-muted rounded small text-black p-1 text-center">If checked each reward will be given once to each user. This will disable the probabilities option.</div>
+            <hr className="my-1 mb-2 bg-dark" />
+            <div className="d-flex justify-content-between align-items-center">
+                <div className="fw-bold">Rewards</div>
+                <div className="btn btn-sm btn-success" onClick={ addReward }><i className="fas fa-plus" /></div>
+            </div>
+            <table className="table-sm">
+                <thead>
+                    <tr>
+                        <td>Badge?</td>
+                        <td>Item Code</td>
+                        <td>Probability</td>
+                        <td></td>
+                    </tr>
+                </thead>
+                <tbody>
+                    { rewards && rewards.map((reward, index) =>
+                        {
+                            return (
+                                <tr key={ index }>
+                                    <td className="d-flex align-items-center justify-content-center">
+                                        <input className="form-check-input" type="checkbox" checked={ reward.isBadge } onChange={(e) => updateReward(index, e.target.checked, reward.itemCode, reward.probability)} />
+                                    </td>
+                                    <td>
+                                        <input type="text" className="form-control form-control-sm" value={ reward.itemCode } onChange={ e => updateReward(index, reward.isBadge, e.target.value, reward.probability) } />
+                                    </td>
+                                    <td>
+                                        <input type="number" className="form-control form-control-sm" value={ reward.probability } onChange={ e => updateReward(index, reward.isBadge, reward.itemCode, Number(e.target.value)) } />
+                                    </td>
+                                    <td>
+                                        { index > 0 && <button className="btn btn-sm btn-danger" onClick={() => removeReward(index) }><i className="fas fa-trash" /></button> }
+                                    </td>
+                                </tr>
+                            )
+                        }) }
+                </tbody>
+            </table>
+        </WiredActionBaseView>
+    );
+}
diff --git a/src/views/wired/views/conditions/actor-has-hand-item/WiredConditionActorHasHandItem.tsx b/src/views/wired/views/conditions/actor-has-hand-item/WiredConditionActorHasHandItem.tsx
index fe746924..5a4fb4c5 100644
--- a/src/views/wired/views/conditions/actor-has-hand-item/WiredConditionActorHasHandItem.tsx
+++ b/src/views/wired/views/conditions/actor-has-hand-item/WiredConditionActorHasHandItem.tsx
@@ -24,7 +24,7 @@ export const WiredConditionActorHasHandItemView: FC<{}> = props =>
     return (
         <WiredConditionBaseView requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ save }>
             <div className="fw-bold">{ LocalizeText('wiredfurni.params.handitem') }</div>
-            <select className="form-select" value={ handItemId } onChange={ (e) => setHandItemId(Number(e.target.value)) }>
+            <select className="form-select form-select-sm" value={ handItemId } onChange={ (e) => setHandItemId(Number(e.target.value)) }>
                 {allowedHanditemIds && allowedHanditemIds.map(value =>
                     {
                         return <option value={ value }>{ LocalizeText('handitem' + value) }</option>

From a0098d8048281028622edc2657d470539c678a42 Mon Sep 17 00:00:00 2001
From: MyNameIsBatman <montevechiol@gmail.com>
Date: Tue, 29 Jun 2021 17:46:08 -0300
Subject: [PATCH 3/4] Fix cols

---
 .../move-and-rotate-furni/WiredActionMoveAndRotateFurniView.tsx | 2 +-
 .../wired/views/actions/move-furni/WiredActionMoveFurniView.tsx | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/views/wired/views/actions/move-and-rotate-furni/WiredActionMoveAndRotateFurniView.tsx b/src/views/wired/views/actions/move-and-rotate-furni/WiredActionMoveAndRotateFurniView.tsx
index 24d9cd22..b12707f0 100644
--- a/src/views/wired/views/actions/move-and-rotate-furni/WiredActionMoveAndRotateFurniView.tsx
+++ b/src/views/wired/views/actions/move-and-rotate-furni/WiredActionMoveAndRotateFurniView.tsx
@@ -48,7 +48,7 @@ export const WiredActionMoveAndRotateFurniView: FC<{}> = props =>
     return (
         <WiredActionBaseView requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_BY_ID_BY_TYPE_OR_FROM_CONTEXT } save={ save }>
             <div className="fw-bold">{ LocalizeText('wiredfurni.params.startdir') }</div>
-            <div className="row row-cold-4">
+            <div className="row row-cols-4">
                 { directionOptions.map(option =>
                     {
                         return (
diff --git a/src/views/wired/views/actions/move-furni/WiredActionMoveFurniView.tsx b/src/views/wired/views/actions/move-furni/WiredActionMoveFurniView.tsx
index 8bd53a9e..1038ba62 100644
--- a/src/views/wired/views/actions/move-furni/WiredActionMoveFurniView.tsx
+++ b/src/views/wired/views/actions/move-furni/WiredActionMoveFurniView.tsx
@@ -66,7 +66,7 @@ export const WiredActionMoveFurniView: FC<{}> = props =>
                     { LocalizeText('wiredfurni.params.movefurni.0') }
                 </label>
             </div>
-            <div className="row row-cold-4">
+            <div className="row row-cols-4">
                 { directionOptions.map(option =>
                     {
                         return (

From 35c542f7db29416ac80fc04803bca8eb6f1c063c Mon Sep 17 00:00:00 2001
From: MyNameIsBatman <montevechiol@gmail.com>
Date: Tue, 29 Jun 2021 21:43:49 -0300
Subject: [PATCH 4/4] Date Condition

---
 .../wired/common/GetWiredConditionLayout.tsx  |  3 +
 .../WiredConditionDateRangeView.tsx           | 62 +++++++++++++++++++
 2 files changed, 65 insertions(+)
 create mode 100644 src/views/wired/views/conditions/date-range/WiredConditionDateRangeView.tsx

diff --git a/src/views/wired/common/GetWiredConditionLayout.tsx b/src/views/wired/common/GetWiredConditionLayout.tsx
index ac6dc69a..068ec848 100644
--- a/src/views/wired/common/GetWiredConditionLayout.tsx
+++ b/src/views/wired/common/GetWiredConditionLayout.tsx
@@ -4,6 +4,7 @@ import { WiredConditionActorIsOnFurniView } from '../views/conditions/actor-is-o
 import { WiredConditionActorIsTeamMemberView } from '../views/conditions/actor-is-team-member/WiredConditionActorIsTeamMemberView';
 import { WiredConditionActorIsWearingBadgeView } from '../views/conditions/actor-is-wearing-badge/WiredConditionActorIsWearingBadgeView';
 import { WiredConditionActorIsWearingEffectView } from '../views/conditions/actor-is-wearing-effect/WiredConditionActorIsWearingEffectView';
+import { WiredConditionDateRangeView } from '../views/conditions/date-range/WiredConditionDateRangeView';
 import { WiredConditionFurniHasAvatarOnView } from '../views/conditions/furni-has-avatar-on/WiredConditionFurniHasAvatarOnView';
 import { WiredConditionFurniHasFurniOnView } from '../views/conditions/furni-has-furni-on/WiredConditionFurniHasFurniOnView';
 import { WiredConditionFurniHasNotFurniOnView } from '../views/conditions/furni-has-not-furni-on/WiredConditionFurniHasNotFurniOnView';
@@ -35,6 +36,8 @@ export function GetWiredConditionLayout(code: number): JSX.Element
         case WiredConditionlayout.ACTOR_IS_WEARING_EFFECT:
         case WiredConditionlayout.NOT_ACTOR_WEARING_EFFECT:
             return <WiredConditionActorIsWearingEffectView />;
+        case WiredConditionlayout.DATE_RANGE_ACTIVE:
+            return <WiredConditionDateRangeView />;
         case WiredConditionlayout.FURNIS_HAVE_AVATARS:
         case WiredConditionlayout.FURNI_NOT_HAVE_HABBO:
             return <WiredConditionFurniHasAvatarOnView />;
diff --git a/src/views/wired/views/conditions/date-range/WiredConditionDateRangeView.tsx b/src/views/wired/views/conditions/date-range/WiredConditionDateRangeView.tsx
new file mode 100644
index 00000000..a0d3c0dd
--- /dev/null
+++ b/src/views/wired/views/conditions/date-range/WiredConditionDateRangeView.tsx
@@ -0,0 +1,62 @@
+import { FC, useCallback, useEffect, useState } from 'react';
+import { LocalizeText } from '../../../../../utils/LocalizeText';
+import { useWiredContext } from '../../../context/WiredContext';
+import { WiredFurniType } from '../../../WiredView.types';
+import { WiredConditionBaseView } from '../base/WiredConditionBaseView';
+
+export const WiredConditionDateRangeView: FC<{}> = props =>
+{
+    const [ startDate, setStartDate ] = useState('');
+    const [ endDate, setEndDate ] = useState('');
+    const { trigger = null, setIntParams = null } = useWiredContext();
+
+    const dateToString = useCallback((date: Date) =>
+    {
+        return `${date.getFullYear()}/${('0' + (date.getMonth() + 1)).slice(-2)}/${('0' + date.getDate()).slice(-2)} ` + `${('0' + date.getHours()).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}`;
+    }, []);
+
+    useEffect(() =>
+    {
+        if(trigger.intData.length >= 2)
+        {
+            let startDate = new Date();
+            let endDate = new Date();
+
+            if(trigger.intData[0] > 0)
+                startDate = new Date((trigger.intData[0] * 1000));
+
+            if(trigger.intData[1] > 0)
+                endDate = new Date((trigger.intData[1] * 1000));
+
+            setStartDate(dateToString(startDate));
+            setEndDate(dateToString(endDate));
+        }
+    }, [ trigger ]);
+
+    const save = useCallback(() =>
+    {
+        let startDateMili = 0;
+        let endDateMili = 0;
+
+        const startDateInstance = new Date(startDate);
+        const endDateInstance = new Date(endDate);
+
+        if(startDateInstance && endDateInstance)
+        {
+            startDateMili = startDateInstance.getTime() / 1000;
+            endDateMili = endDateInstance.getTime() / 1000;
+        }
+
+        setIntParams([startDateMili, endDateMili]);
+    }, [ startDate, endDate, setIntParams ]);
+    
+    return (
+        <WiredConditionBaseView requiresFurni={ WiredFurniType.STUFF_SELECTION_OPTION_NONE } save={ save }>
+            <div className="fw-bold">{ LocalizeText('wiredfurni.params.startdate') }</div>
+            <input type="text" className="form-control form-control-sm" value={ startDate } onChange={ (e) => setStartDate(e.target.value) } />
+            <hr className="my-1 mb-2 bg-dark" />
+            <div className="fw-bold">{ LocalizeText('wiredfurni.params.enddate') }</div>
+            <input type="text" className="form-control form-control-sm" value={ endDate } onChange={ (e) => setEndDate(e.target.value) } />
+        </WiredConditionBaseView>
+    );
+}